}
-LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
- LOperand* string = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LStringLength(string));
-}
-
-
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
info()->MarkAsDeferredCalling();
LOperand* size = instr->size()->IsConstant()
V(StringCharCodeAt) \
V(StringCharFromCode) \
V(StringCompareAndBranch) \
- V(StringLength) \
V(SubI) \
V(RSubI) \
V(TaggedToI) \
};
-class LStringLength: public LTemplateInstruction<1, 1, 0> {
- public:
- explicit LStringLength(LOperand* string) {
- inputs_[0] = string;
- }
-
- LOperand* string() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
- DECLARE_HYDROGEN_ACCESSOR(StringLength)
-};
-
-
class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
public:
explicit LCheckFunction(LOperand* value) {
}
-void LCodeGen::DoStringLength(LStringLength* instr) {
- Register string = ToRegister(instr->string());
- Register result = ToRegister(instr->result());
- __ ldr(result, FieldMemOperand(string, String::kLengthOffset));
-}
-
-
void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
LOperand* input = instr->value();
ASSERT(input->IsRegister() || input->IsStackSlot());
}
+Range* HLoadNamedField::InferRange(Zone* zone) {
+ if (access().IsStringLength()) {
+ return new(zone) Range(0, String::kMaxLength);
+ }
+ return HValue::InferRange(zone);
+}
+
+
Range* HLoadKeyed::InferRange(Zone* zone) {
switch (elements_kind()) {
case EXTERNAL_PIXEL_ELEMENTS:
}
-HInstruction* HStringLength::New(Zone* zone, HValue* context, HValue* string) {
- if (FLAG_fold_constants && string->IsConstant()) {
- HConstant* c_string = HConstant::cast(string);
- if (c_string->HasStringValue()) {
- return HConstant::New(zone, context, c_string->StringValue()->length());
- }
- }
- return new(zone) HStringLength(string);
-}
-
-
HInstruction* HUnaryMathOperation::New(
Zone* zone, HValue* context, HValue* value, BuiltinFunctionId op) {
do {
instr->SetGVNFlag(is_store
? kChangesArrayLengths : kDependsOnArrayLengths);
break;
+ case kStringLengths:
+ instr->SetGVNFlag(is_store
+ ? kChangesStringLengths : kDependsOnStringLengths);
+ break;
case kInobject:
instr->SetGVNFlag(is_store
? kChangesInobjectFields : kDependsOnInobjectFields);
switch (portion()) {
case kArrayLengths:
+ case kStringLengths:
stream->Add("%length");
break;
case kElementsPointer:
V(StringCharCodeAt) \
V(StringCharFromCode) \
V(StringCompareAndBranch) \
- V(StringLength) \
V(Sub) \
V(ThisFunction) \
V(Throw) \
#define GVN_UNTRACKED_FLAG_LIST(V) \
V(ArrayElements) \
V(ArrayLengths) \
+ V(StringLengths) \
V(BackingStoreFields) \
V(Calls) \
V(ContextSlots) \
return portion() == kExternalMemory;
}
+ inline bool IsStringLength() const {
+ return portion() == kStringLengths;
+ }
+
inline int offset() const {
return OffsetField::decode(value_);
}
FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
}
+ static HObjectAccess ForStringLength() {
+ STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
+ return HObjectAccess(
+ kStringLengths,
+ String::kLengthOffset,
+ FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
+ }
+
static HObjectAccess ForPropertiesPointer() {
return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
}
enum Portion {
kMaps, // map of an object
kArrayLengths, // the length of an array
+ kStringLengths, // the length of a string
kElementsPointer, // elements pointer
kBackingStore, // some field in the backing store
kDouble, // some double field
}
return Representation::Tagged();
}
+ virtual Range* InferRange(Zone* zone);
virtual void PrintDataTo(StringStream* stream);
DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
};
-class HStringLength: public HUnaryOperation {
- public:
- static HInstruction* New(Zone* zone, HValue* context, HValue* string);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StringLength)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- virtual Range* InferRange(Zone* zone) {
- return new(zone) Range(0, String::kMaxLength);
- }
-
- private:
- explicit HStringLength(HValue* string)
- : HUnaryOperation(string, HType::Smi()) {
- STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- }
-
- virtual bool IsDeletable() const { return true; }
-};
-
-
template <int V>
class HMaterializedLiteral: public HTemplateInstruction<V> {
public:
HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
- HObjectAccess access) {
+ HObjectAccess access,
+ HValue* typecheck) {
if (FLAG_track_double_fields && access.representation().IsDouble()) {
// load the heap number
HLoadNamedField* heap_number = Add<HLoadNamedField>(
heap_number->set_type(HType::HeapNumber());
// load the double value from it
return New<HLoadNamedField>(heap_number,
- HObjectAccess::ForHeapNumberValue());
+ HObjectAccess::ForHeapNumberValue(),
+ typecheck);
}
- return New<HLoadNamedField>(object, access);
+ return New<HLoadNamedField>(object, access, typecheck);
+}
+
+
+HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object,
+ HValue* typecheck) {
+ if (FLAG_fold_constants && object->IsConstant()) {
+ HConstant* constant = HConstant::cast(object);
+ if (constant->HasStringValue()) {
+ return New<HConstant>(constant->StringValue()->length());
+ }
+ }
+ return BuildLoadNamedField(
+ object, HObjectAccess::ForStringLength(), typecheck);
}
if (expr->IsStringLength()) {
HValue* string = Pop();
BuildCheckHeapObject(string);
- AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
- instr = NewUncasted<HStringLength>(string);
+ HInstruction* checkstring =
+ AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
+ instr = BuildLoadStringLength(string, checkstring);
} else if (expr->IsStringAccess()) {
CHECK_ALIVE(VisitForValue(expr->key()));
HValue* index = Pop();
}
}
BuildCheckHeapObject(string);
- AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
- HInstruction* length = Add<HStringLength>(string);
+ HValue* checkstring =
+ AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
+ HInstruction* length = BuildLoadStringLength(string, checkstring);
+ AddInstruction(length);
HInstruction* checked_index = Add<HBoundsCheck>(index, length);
return New<HStringCharCodeAt>(string, checked_index);
}
LoadKeyedHoleMode load_mode,
KeyedAccessStoreMode store_mode);
- HLoadNamedField* BuildLoadNamedField(
- HValue* object,
- HObjectAccess access);
-
HInstruction* AddExternalArrayElementAccess(
HValue* external_elements,
HValue* checked_key,
LoadKeyedHoleMode load_mode,
KeyedAccessStoreMode store_mode);
+ HLoadNamedField* BuildLoadNamedField(
+ HValue* object,
+ HObjectAccess access,
+ HValue* typecheck = NULL);
+ HInstruction* BuildLoadStringLength(HValue* object, HValue* typecheck = NULL);
HStoreNamedField* AddStoreMapConstant(HValue *object, Handle<Map>);
HLoadNamedField* AddLoadElements(HValue *object, HValue *typecheck = NULL);
HLoadNamedField* AddLoadFixedArrayLength(HValue *object);
}
-void LCodeGen::DoStringLength(LStringLength* instr) {
- Register string = ToRegister(instr->string());
- Register result = ToRegister(instr->result());
- __ mov(result, FieldOperand(string, String::kLengthOffset));
-}
-
-
void LCodeGen::DoStringAdd(LStringAdd* instr) {
EmitPushTaggedOperand(instr->left());
EmitPushTaggedOperand(instr->right());
}
-LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
- LOperand* string = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LStringLength(string));
-}
-
-
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
info()->MarkAsDeferredCalling();
LOperand* context = UseAny(instr->context());
V(StringCharCodeAt) \
V(StringCharFromCode) \
V(StringCompareAndBranch) \
- V(StringLength) \
V(SubI) \
V(TaggedToI) \
V(TaggedToINoSSE2) \
};
-class LStringLength: public LTemplateInstruction<1, 1, 0> {
- public:
- explicit LStringLength(LOperand* string) {
- inputs_[0] = string;
- }
-
- LOperand* string() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
- DECLARE_HYDROGEN_ACCESSOR(StringLength)
-};
-
-
class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
public:
explicit LCheckFunction(LOperand* value) {
}
-void LCodeGen::DoStringLength(LStringLength* instr) {
- Register string = ToRegister(instr->string());
- Register result = ToRegister(instr->result());
- __ lw(result, FieldMemOperand(string, String::kLengthOffset));
-}
-
-
void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
LOperand* input = instr->value();
ASSERT(input->IsRegister() || input->IsStackSlot());
}
-LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
- LOperand* string = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LStringLength(string));
-}
-
-
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
info()->MarkAsDeferredCalling();
LOperand* size = instr->size()->IsConstant()
V(StringCharCodeAt) \
V(StringCharFromCode) \
V(StringCompareAndBranch) \
- V(StringLength) \
V(SubI) \
V(TaggedToI) \
V(ThisFunction) \
};
-class LStringLength: public LTemplateInstruction<1, 1, 0> {
- public:
- explicit LStringLength(LOperand* string) {
- inputs_[0] = string;
- }
-
- LOperand* string() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
- DECLARE_HYDROGEN_ACCESSOR(StringLength)
-};
-
-
class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
public:
explicit LCheckFunction(LOperand* value) {
}
-void LCodeGen::DoStringLength(LStringLength* instr) {
- Register string = ToRegister(instr->string());
- Register result = ToRegister(instr->result());
- __ movq(result, FieldOperand(string, String::kLengthOffset));
-}
-
-
void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
LOperand* input = instr->value();
ASSERT(input->IsRegister() || input->IsStackSlot());
}
-LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
- LOperand* string = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LStringLength(string));
-}
-
-
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
info()->MarkAsDeferredCalling();
LOperand* size = instr->size()->IsConstant()
V(StringCharCodeAt) \
V(StringCharFromCode) \
V(StringCompareAndBranch) \
- V(StringLength) \
V(SubI) \
V(TaggedToI) \
V(ThisFunction) \
};
-class LStringLength: public LTemplateInstruction<1, 1, 0> {
- public:
- explicit LStringLength(LOperand* string) {
- inputs_[0] = string;
- }
-
- LOperand* string() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
- DECLARE_HYDROGEN_ACCESSOR(StringLength)
-};
-
-
class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
public:
explicit LCheckFunction(LOperand* value) {