V(Deoptimize) \
V(Div) \
V(DummyUse) \
- V(ElementsKind) \
V(EnterInlined) \
V(EnvironmentMarker) \
V(ForceRepresentation) \
V(ForInPrepareMap) \
V(FunctionLiteral) \
V(GetCachedArrayIndex) \
- V(GlobalObject) \
- V(GlobalReceiver) \
V(Goto) \
V(HasCachedArrayIndexAndBranch) \
V(HasInstanceTypeAndBranch) \
V(IsUndetectableAndBranch) \
V(LeaveInlined) \
V(LoadContextSlot) \
- V(LoadExternalArrayPointer) \
V(LoadFieldByIndex) \
V(LoadFunctionPrototype) \
V(LoadGlobalCell) \
V(Mod) \
V(Mul) \
V(OsrEntry) \
- V(OuterContext) \
V(Parameter) \
V(Power) \
V(PushArgument) \
V(StringCompareAndBranch) \
V(Sub) \
V(ThisFunction) \
- V(Throw) \
V(ToFastProperties) \
V(TransitionElementsKind) \
V(TrapAllocationMemento) \
V(Typeof) \
V(TypeofIsAndBranch) \
V(UnaryMathOperation) \
+ V(NullarySIMDOperation) \
+ V(UnarySIMDOperation) \
+ V(BinarySIMDOperation) \
+ V(TernarySIMDOperation) \
+ V(QuarternarySIMDOperation) \
V(UnknownOSRValue) \
V(UseConst) \
- V(ValueOf) \
V(WrapReceiver)
#define GVN_TRACKED_FLAG_LIST(V) \
static HType TaggedNumber() { return HType(kTaggedNumber); }
static HType Smi() { return HType(kSmi); }
static HType HeapNumber() { return HType(kHeapNumber); }
+ static HType Float32x4() { return HType(kFloat32x4); }
+ static HType Int32x4() { return HType(kInt32x4); }
static HType String() { return HType(kString); }
static HType Boolean() { return HType(kBoolean); }
static HType NonPrimitive() { return HType(kNonPrimitive); }
return ((type_ & kHeapNumber) == kHeapNumber);
}
+ bool IsFloat32x4() const {
+ return ((type_ & kFloat32x4) == kFloat32x4);
+ }
+
+ bool IsInt32x4() const {
+ return ((type_ & kInt32x4) == kInt32x4);
+ }
+
+ bool IsSIMD128() const {
+ return IsFloat32x4() || IsInt32x4();
+ }
+
bool IsString() const {
return ((type_ & kString) == kString);
}
bool IsNonString() const {
- return IsTaggedPrimitive() || IsSmi() || IsHeapNumber() ||
+ return IsTaggedPrimitive() || IsSmi() || IsHeapNumber() || IsSIMD128() ||
IsBoolean() || IsJSArray();
}
}
bool IsHeapObject() const {
- return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive();
+ return IsHeapNumber() || IsSIMD128() || IsString() ||
+ IsBoolean() || IsNonPrimitive();
}
bool ToStringOrToNumberCanBeObserved(Representation representation) {
case kTaggedNumber: // fallthru
case kSmi: // fallthru
case kHeapNumber: // fallthru
+ case kFloat32x4: // fallthru
+ case kInt32x4: // fallthru
case kString: // fallthru
case kBoolean:
return false;
}
static HType TypeFromValue(Handle<Object> value);
+ static HType TypeFromRepresentation(Representation representation);
const char* ToString();
kTaggedNumber = 0xd, // 0000 0000 0000 1101
kSmi = 0x1d, // 0000 0000 0001 1101
kHeapNumber = 0x2d, // 0000 0000 0010 1101
- kString = 0x45, // 0000 0000 0100 0101
- kBoolean = 0x85, // 0000 0000 1000 0101
- kNonPrimitive = 0x101, // 0000 0001 0000 0001
- kJSObject = 0x301, // 0000 0011 0000 0001
- kJSArray = 0x701 // 0000 0111 0000 0001
+ kFloat32x4 = 0x45, // 0000 0000 0100 0101
+ kInt32x4 = 0x85, // 0000 0000 1000 0101
+ kString = 0x105, // 0000 0001 0000 0101
+ kBoolean = 0x205, // 0000 0010 1000 0101
+ kNonPrimitive = 0x401, // 0000 0100 0000 0001
+ kJSObject = 0xc01, // 0000 1100 0000 0001
+ kJSArray = 0x1c01 // 0001 1100 0000 0001
};
// Make sure type fits in int16.
GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
#undef DECLARE_FLAG
- kAfterLastFlag,
- kLastFlag = kAfterLastFlag - 1,
+ kNumberOfFlags,
#define COUNT_FLAG(type) + 1
kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG)
#undef COUNT_FLAG
HType t = type();
if (t.IsSmi()) return Representation::Smi();
if (t.IsHeapNumber()) return Representation::Double();
+ if (t.IsFloat32x4()) return Representation::Float32x4();
+ if (t.IsInt32x4()) return Representation::Int32x4();
if (t.IsHeapObject()) return r;
return Representation::None();
}
// This function must be overridden for instructions which have the
// kTrackSideEffectDominators flag set, to track instructions that are
// dominating side effects.
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ // It returns true if it removed an instruction which had side effects.
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) {
UNREACHABLE();
+ return false;
}
// Check if this instruction has some reason that prevents elimination.
DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
HBasicBlock*, HBasicBlock*);
+ virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
+ if (known_successor_index() != kNoKnownSuccessorIndex) {
+ *block = SuccessorAt(known_successor_index());
+ return true;
+ }
+ *block = NULL;
+ return false;
+ }
+
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+ static const int kNoKnownSuccessorIndex = -1;
+ int known_successor_index() const { return known_successor_index_; }
+ void set_known_successor_index(int known_successor_index) {
+ known_successor_index_ = known_successor_index;
+ }
+
Unique<Map> map() const { return map_; }
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
HBasicBlock* true_target = NULL,
HBasicBlock* false_target = NULL)
: HUnaryControlInstruction(value, true_target, false_target),
- map_(Unique<Map>(map)) {
+ known_successor_index_(kNoKnownSuccessorIndex), map_(Unique<Map>(map)) {
ASSERT(!map.is_null());
}
+ int known_successor_index_;
Unique<Map> map_;
};
};
-class HThrow V8_FINAL : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HThrow, HValue*);
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* value() { return OperandAt(1); }
-
- DECLARE_CONCRETE_INSTRUCTION(Throw)
-
- private:
- HThrow(HValue* context, HValue* value) {
- SetOperandAt(0, context);
- SetOperandAt(1, value);
- SetAllSideEffects();
- }
-};
-
-
class HUseConst V8_FINAL : public HUnaryOperation {
public:
DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
if (value->representation().IsSmi() || value->type().IsSmi()) {
set_type(HType::Smi());
} else {
- set_type(HType::TaggedNumber());
+ if (to.IsFloat32x4()) {
+ set_type(HType::Float32x4());
+ } else if (to.IsInt32x4()) {
+ set_type(HType::Int32x4());
+ } else {
+ set_type(HType::TaggedNumber());
+ }
if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
}
}
enum InliningKind {
- NORMAL_RETURN, // Normal function/method call and return.
- DROP_EXTRA_ON_RETURN, // Drop an extra value from the environment on return.
+ NORMAL_RETURN, // Drop the function from the environment on return.
CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
};
-class HOuterContext V8_FINAL : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HOuterContext, HValue*);
-
- DECLARE_CONCRETE_INSTRUCTION(OuterContext);
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
-
- private:
- explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
class HDeclareGlobals V8_FINAL : public HUnaryOperation {
public:
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
};
-class HGlobalObject V8_FINAL : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(HGlobalObject);
-
- DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
-
- private:
- explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
-class HGlobalReceiver V8_FINAL : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HGlobalReceiver, HValue*);
-
- DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
-
- private:
- explicit HGlobalReceiver(HValue* global_object)
- : HUnaryOperation(global_object) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
template <int V>
class HCall : public HTemplateInstruction<V> {
public:
};
-enum CallMode {
- NORMAL_CALL,
- TAIL_CALL,
- NORMAL_CONTEXTUAL_CALL
-};
-
-
class HCallFunction V8_FINAL : public HBinaryCall {
public:
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(
- HCallFunction, HValue*, int, CallMode);
+ HCallFunction, HValue*, int, CallFunctionFlags);
- bool IsTailCall() const { return call_mode_ == TAIL_CALL; }
- bool IsContextualCall() const { return call_mode_ == NORMAL_CONTEXTUAL_CALL; }
HValue* context() { return first(); }
HValue* function() { return second(); }
+ CallFunctionFlags function_flags() const { return function_flags_; }
DECLARE_CONCRETE_INSTRUCTION(CallFunction)
- virtual int argument_delta() const V8_OVERRIDE {
- if (IsTailCall()) return 0;
- return -argument_count();
- }
+ virtual int argument_delta() const V8_OVERRIDE { return -argument_count(); }
private:
HCallFunction(HValue* context,
HValue* function,
int argument_count,
- CallMode mode = NORMAL_CALL)
- : HBinaryCall(context, function, argument_count), call_mode_(mode) {
+ CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS)
+ : HBinaryCall(context, function, argument_count), function_flags_(flags) {
}
- CallMode call_mode_;
+ CallFunctionFlags function_flags_;
};
};
-class HElementsKind V8_FINAL : public HUnaryOperation {
- public:
- explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnElementsKind);
- }
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
-
- protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
-
- private:
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
class HUnaryMathOperation V8_FINAL : public HTemplateInstruction<2> {
public:
static HInstruction* New(Zone* zone,
};
-class HLoadExternalArrayPointer V8_FINAL : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HLoadExternalArrayPointer, HValue*);
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- virtual HType CalculateInferredType() V8_OVERRIDE {
- return HType::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
-
- protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
-
- private:
- explicit HLoadExternalArrayPointer(HValue* value)
- : HUnaryOperation(value) {
- set_representation(Representation::External());
- // The result of this instruction is idempotent as long as its inputs don't
- // change. The external array of a specialized array elements object cannot
- // change once set, so it's no necessary to introduce any additional
- // dependencies on top of the inputs.
- SetFlag(kUseGVN);
- }
-
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
class HCheckMaps V8_FINAL : public HTemplateInstruction<2> {
public:
static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
return Representation::Tagged();
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE;
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
return is_not_in_new_space_;
}
- bool ImmortalImmovable() const {
- if (has_int32_value_) {
- return false;
- }
- if (has_double_value_) {
- if (IsSpecialDouble()) {
- return true;
- }
- return false;
- }
- if (has_external_reference_value_) {
- return false;
- }
-
- ASSERT(!object_.handle().is_null());
- Heap* heap = isolate()->heap();
- ASSERT(!object_.IsKnownGlobal(heap->minus_zero_value()));
- ASSERT(!object_.IsKnownGlobal(heap->nan_value()));
- return
- object_.IsKnownGlobal(heap->undefined_value()) ||
- object_.IsKnownGlobal(heap->null_value()) ||
- object_.IsKnownGlobal(heap->true_value()) ||
- object_.IsKnownGlobal(heap->false_value()) ||
- object_.IsKnownGlobal(heap->the_hole_value()) ||
- object_.IsKnownGlobal(heap->empty_string()) ||
- object_.IsKnownGlobal(heap->empty_fixed_array());
- }
+ bool ImmortalImmovable() const;
bool IsCell() const {
return is_cell_;
public:
DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
+ virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
+
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
return Representation::Tagged();
}
virtual HValue* Canonicalize() V8_OVERRIDE;
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+ bool known_function() const { return known_function_; }
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
private:
HWrapReceiver(HValue* receiver, HValue* function) {
+ known_function_ = function->IsConstant() &&
+ HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
set_representation(Representation::Tagged());
SetOperandAt(0, receiver);
SetOperandAt(1, function);
+ SetFlag(kUseGVN);
}
+
+ bool known_function_;
};
DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
+ protected:
+ virtual int RedefinedOperandIndex() { return 0; }
+
private:
HIsStringAndBranch(HValue* value,
HBasicBlock* true_target = NULL,
protected:
virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
+ virtual int RedefinedOperandIndex() { return 0; }
private:
HIsSmiAndBranch(HValue* value,
Handle<String> type_literal() { return type_literal_; }
bool compares_number_type() { return compares_number_type_; }
+ bool compares_float32x4_type() { return compares_float32x4_type_; }
+ bool compares_int32x4_type() { return compares_int32x4_type_; }
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
type_literal_(type_literal) {
Heap* heap = type_literal->GetHeap();
compares_number_type_ = type_literal->Equals(heap->number_string());
+ compares_float32x4_type_ = type_literal->Equals(heap->float32x4_string());
+ compares_int32x4_type_ = type_literal->Equals(heap->int32x4_string());
}
Handle<String> type_literal_;
bool compares_number_type_ : 1;
+ bool compares_float32x4_type_ : 1;
+ bool compares_int32x4_type_ : 1;
};
flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE;
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
return ImmutableField::decode(value_);
}
+ // Returns true if access is being made to an in-object property that
+ // was already added to the object.
+ inline bool existing_inobject_property() const {
+ return ExistingInobjectPropertyField::decode(value_);
+ }
+
inline HObjectAccess WithRepresentation(Representation representation) {
- return HObjectAccess(portion(), offset(), representation, name());
+ return HObjectAccess(portion(), offset(), representation, name(),
+ immutable(), existing_inobject_property());
}
static HObjectAccess ForHeapNumberValue() {
static HObjectAccess ForAllocationSiteOffset(int offset);
static HObjectAccess ForAllocationSiteList() {
- return HObjectAccess(kExternalMemory, 0, Representation::Tagged());
+ return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
+ Handle<String>::null(), false, false);
}
static HObjectAccess ForFixedArrayLength() {
Representation::UInteger8());
}
+ static HObjectAccess ForMapPrototype() {
+ return HObjectAccess(kInobject, Map::kPrototypeOffset);
+ }
+
static HObjectAccess ForPropertyCellValue() {
return HObjectAccess(kInobject, PropertyCell::kValueOffset);
}
}
static HObjectAccess ForCounter() {
- return HObjectAccess(kExternalMemory, 0, Representation::Integer32());
+ return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
+ Handle<String>::null(), false, false);
}
// Create an access to an offset in a fixed array header.
static HObjectAccess ForFixedArrayHeader(int offset);
// Create an access to an in-object property in a JSObject.
- static HObjectAccess ForJSObjectOffset(int offset,
+ // This kind of access must be used when the object |map| is known and
+ // in-object properties are being accessed. Accesses of the in-object
+ // properties can have different semantics depending on whether corresponding
+ // property was added to the map or not.
+ static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
Representation representation = Representation::Tagged());
+ // Create an access to an in-object property in a JSObject.
+ // This kind of access can be used for accessing object header fields or
+ // in-object properties if the map of the object is not known.
+ static HObjectAccess ForObservableJSObjectOffset(int offset,
+ Representation representation = Representation::Tagged()) {
+ return ForMapAndOffset(Handle<Map>::null(), offset, representation);
+ }
+
// Create an access to an in-object property in a JSArray.
static HObjectAccess ForJSArrayOffset(int offset);
static HObjectAccess ForCellPayload(Isolate* isolate);
static HObjectAccess ForJSTypedArrayLength() {
- return HObjectAccess::ForJSObjectOffset(JSTypedArray::kLengthOffset);
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSTypedArray::kLengthOffset);
}
static HObjectAccess ForJSArrayBufferBackingStore() {
- return HObjectAccess::ForJSObjectOffset(
+ return HObjectAccess::ForObservableJSObjectOffset(
JSArrayBuffer::kBackingStoreOffset, Representation::External());
}
static HObjectAccess ForExternalArrayExternalPointer() {
- return HObjectAccess::ForJSObjectOffset(
+ return HObjectAccess::ForObservableJSObjectOffset(
ExternalArray::kExternalPointerOffset, Representation::External());
}
static HObjectAccess ForJSArrayBufferViewWeakNext() {
- return HObjectAccess::ForJSObjectOffset(JSArrayBufferView::kWeakNextOffset);
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSArrayBufferView::kWeakNextOffset);
}
static HObjectAccess ForJSArrayBufferWeakFirstView() {
- return HObjectAccess::ForJSObjectOffset(
+ return HObjectAccess::ForObservableJSObjectOffset(
JSArrayBuffer::kWeakFirstViewOffset);
}
static HObjectAccess ForJSArrayBufferViewBuffer() {
- return HObjectAccess::ForJSObjectOffset(JSArrayBufferView::kBufferOffset);
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSArrayBufferView::kBufferOffset);
}
static HObjectAccess ForJSArrayBufferViewByteOffset() {
- return HObjectAccess::ForJSObjectOffset(
+ return HObjectAccess::ForObservableJSObjectOffset(
JSArrayBufferView::kByteOffsetOffset);
}
static HObjectAccess ForJSArrayBufferViewByteLength() {
- return HObjectAccess::ForJSObjectOffset(
+ return HObjectAccess::ForObservableJSObjectOffset(
JSArrayBufferView::kByteLengthOffset);
}
+ static HObjectAccess ForGlobalObjectNativeContext() {
+ return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
+ }
+
void PrintTo(StringStream* stream);
inline bool Equals(HObjectAccess that) const {
HObjectAccess(Portion portion, int offset,
Representation representation = Representation::Tagged(),
Handle<String> name = Handle<String>::null(),
- bool immutable = false)
+ bool immutable = false,
+ bool existing_inobject_property = true)
: value_(PortionField::encode(portion) |
RepresentationField::encode(representation.kind()) |
ImmutableField::encode(immutable ? 1 : 0) |
+ ExistingInobjectPropertyField::encode(
+ existing_inobject_property ? 1 : 0) |
OffsetField::encode(offset)),
name_(name) {
// assert that the fields decode correctly
ASSERT(this->offset() == offset);
ASSERT(this->portion() == portion);
ASSERT(this->immutable() == immutable);
+ ASSERT(this->existing_inobject_property() == existing_inobject_property);
ASSERT(RepresentationField::decode(value_) == representation.kind());
+ ASSERT(!this->existing_inobject_property() || IsInobject());
}
class PortionField : public BitField<Portion, 0, 3> {};
class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
class ImmutableField : public BitField<bool, 7, 1> {};
- class OffsetField : public BitField<int, 8, 24> {};
+ class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
+ class OffsetField : public BitField<int, 9, 23> {};
uint32_t value_; // encodes portion, representation, immutable, and offset
Handle<String> name_;
};
-class HLoadNamedField V8_FINAL : public HTemplateInstruction<1> {
+class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
public:
- DECLARE_INSTRUCTION_FACTORY_P2(HLoadNamedField, HValue*, HObjectAccess);
+ DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*, HValue*,
+ HObjectAccess);
HValue* object() { return OperandAt(0); }
- bool HasTypeCheck() { return object()->IsCheckMaps(); }
+ HValue* dependency() {
+ ASSERT(HasDependency());
+ return OperandAt(1);
+ }
+ bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
HObjectAccess access() const { return access_; }
Representation field_representation() const {
return access_.representation();
}
private:
- HLoadNamedField(HValue* object, HObjectAccess access) : access_(access) {
+ HLoadNamedField(HValue* object,
+ HValue* dependency,
+ HObjectAccess access) : access_(access) {
ASSERT(object != NULL);
SetOperandAt(0, object);
+ SetOperandAt(1, dependency != NULL ? dependency : object);
Representation representation = access.representation();
if (representation.IsInteger8() ||
elements_kind == FLOAT32_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
set_representation(Representation::Double());
+ } else if (IsFloat32x4ElementsKind(elements_kind)) {
+ set_representation(CPU::SupportsSIMD128InCrankshaft() ?
+ Representation::Float32x4() : Representation::Tagged());
+ } else if (IsInt32x4ElementsKind(elements_kind)) {
+ set_representation(CPU::SupportsSIMD128InCrankshaft() ?
+ Representation::Int32x4() : Representation::Tagged());
} else {
set_representation(Representation::Integer32());
}
// Indicates whether the store is a store to an entry that was previously
// initialized or not.
enum StoreFieldOrKeyedMode {
+ // The entry could be either previously initialized or not.
INITIALIZING_STORE,
+ // At the time of this store it is guaranteed that the entry is already
+ // initialized.
STORE_TO_INITIALIZED_ENTRY
};
}
return Representation::Tagged();
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE {
ASSERT(side_effect == kChangesNewSpacePromotion);
new_space_dominator_ = dominator;
+ return false;
}
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
write_barrier_mode_(UPDATE_WRITE_BARRIER),
has_transition_(false),
store_mode_(store_mode) {
+ if (!FLAG_smi_x64_store_opt) store_mode_ = INITIALIZING_STORE;
+ // Stores to a non existing in-object property are allowed only to the
+ // newly allocated objects (via HAllocate or HInnerAllocatedObject).
+ ASSERT(!access.IsInobject() || access.existing_inobject_property() ||
+ obj->IsAllocate() || obj->IsInnerAllocatedObject());
SetOperandAt(0, obj);
SetOperandAt(1, val);
SetOperandAt(2, obj);
}
ASSERT_EQ(index, 2);
+
if (IsDoubleOrFloatElementsKind(elements_kind())) {
return Representation::Double();
}
+ if (IsFloat32x4ElementsKind(elements_kind())) {
+ return CPU::SupportsSIMD128InCrankshaft() ?
+ Representation::Float32x4() : Representation::Tagged();
+ }
+ if (IsInt32x4ElementsKind(elements_kind())) {
+ return CPU::SupportsSIMD128InCrankshaft() ?
+ Representation::Int32x4() : Representation::Tagged();
+ }
if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
return Representation::Integer32();
}
if (IsDoubleOrFloatElementsKind(elements_kind())) {
return Representation::Double();
}
+ if (IsFloat32x4ElementsKind(elements_kind())) {
+ return CPU::SupportsSIMD128InCrankshaft() ?
+ Representation::Float32x4() : Representation::Tagged();
+ }
+ if (IsInt32x4ElementsKind(elements_kind())) {
+ return CPU::SupportsSIMD128InCrankshaft() ?
+ Representation::Int32x4() : Representation::Tagged();
+ }
if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
return Representation::Integer32();
}
return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE {
ASSERT(side_effect == kChangesNewSpacePromotion);
new_space_dominator_ = dominator;
+ return false;
}
HValue* new_space_dominator() const { return new_space_dominator_; }
is_uninitialized_(false),
store_mode_(store_mode),
new_space_dominator_(NULL) {
+ if (!FLAG_smi_x64_store_opt) store_mode_ = INITIALIZING_STORE;
SetOperandAt(0, obj);
SetOperandAt(1, key);
SetOperandAt(2, val);
};
-class HValueOf V8_FINAL : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HValueOf, HValue*);
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ValueOf)
-
- private:
- explicit HValueOf(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- }
-
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
class HDateField V8_FINAL : public HUnaryOperation {
public:
DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
};
+class HNullarySIMDOperation V8_FINAL : public HTemplateInstruction<1> {
+ public:
+ static HInstruction* New(Zone* zone,
+ HValue* context,
+ BuiltinFunctionId op);
+
+ HValue* context() { return OperandAt(0); }
+
+ virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+
+ virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
+ return Representation::Tagged();
+ }
+
+ BuiltinFunctionId op() const { return op_; }
+ const char* OpName() const;
+
+ DECLARE_CONCRETE_INSTRUCTION(NullarySIMDOperation)
+
+ protected:
+ virtual bool DataEquals(HValue* other) V8_OVERRIDE {
+ HNullarySIMDOperation* b = HNullarySIMDOperation::cast(other);
+ return op_ == b->op();
+ }
+
+ private:
+ HNullarySIMDOperation(HValue* context, BuiltinFunctionId op)
+ : HTemplateInstruction<1>(HType::None()), op_(op) {
+ SetOperandAt(0, context);
+ switch (op) {
+#define SIMD_NULLARY_OPERATION_CASE_ITEM(p1, p2, name, representation) \
+ case k##name: \
+ set_representation(Representation::representation()); \
+ set_type(HType::TypeFromRepresentation(representation_)); \
+ break;
+SIMD_NULLARY_OPERATIONS(SIMD_NULLARY_OPERATION_CASE_ITEM)
+#undef SIMD_NULLARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ }
+ SetFlag(kUseGVN);
+ }
+
+ virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+
+ BuiltinFunctionId op_;
+};
+
+
+class HUnarySIMDOperation V8_FINAL : public HTemplateInstruction<2> {
+ public:
+ static HInstruction* New(Zone* zone,
+ HValue* context,
+ HValue* value,
+ BuiltinFunctionId op,
+ Representation to = Representation::Float32x4());
+
+ HValue* context() { return OperandAt(0); }
+ HValue* value() { return OperandAt(1); }
+
+ virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+
+ virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
+ if (index == 0) {
+ return Representation::Tagged();
+ } else if (op_ == kSIMD128Change) {
+ return value()->representation();
+ } else {
+ switch (op_) {
+#define SIMD_UNARY_OPERATION_CASE_ITEM(p1, p2, name, p4, representation) \
+ case k##name: \
+ return Representation::representation();
+SIMD_UNARY_OPERATIONS(SIMD_UNARY_OPERATION_CASE_ITEM)
+SIMD_UNARY_OPERATIONS_FOR_PROPERTY_ACCESS(SIMD_UNARY_OPERATION_CASE_ITEM)
+#undef SIMD_UNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return Representation::None();
+ }
+ }
+ }
+
+ BuiltinFunctionId op() const { return op_; }
+ const char* OpName() const;
+
+ DECLARE_CONCRETE_INSTRUCTION(UnarySIMDOperation)
+
+ protected:
+ virtual bool DataEquals(HValue* other) V8_OVERRIDE {
+ HUnarySIMDOperation* b = HUnarySIMDOperation::cast(other);
+ return op_ == b->op();
+ }
+
+ private:
+ HUnarySIMDOperation(HValue* context, HValue* value, BuiltinFunctionId op,
+ Representation to = Representation::Float32x4())
+ : HTemplateInstruction<2>(HType::None()), op_(op) {
+ SetOperandAt(0, context);
+ SetOperandAt(1, value);
+ switch (op) {
+ case kSIMD128Change:
+ set_representation(to);
+ set_type(HType::TypeFromRepresentation(to));
+ break;
+#define SIMD_UNARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5) \
+ case k##name: \
+ set_representation(Representation::representation()); \
+ set_type(HType::TypeFromRepresentation(representation_)); \
+ break;
+SIMD_UNARY_OPERATIONS(SIMD_UNARY_OPERATION_CASE_ITEM)
+SIMD_UNARY_OPERATIONS_FOR_PROPERTY_ACCESS(SIMD_UNARY_OPERATION_CASE_ITEM)
+#undef SIMD_UNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ }
+ SetFlag(kUseGVN);
+ }
+
+ virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+
+ BuiltinFunctionId op_;
+};
+
+
+class HBinarySIMDOperation V8_FINAL : public HTemplateInstruction<3> {
+ public:
+ static HInstruction* New(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right,
+ BuiltinFunctionId op);
+
+ HValue* context() { return OperandAt(0); }
+ HValue* left() { return OperandAt(1); }
+ HValue* right() { return OperandAt(2); }
+
+ virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+
+ virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
+ if (index == 0) {
+ return Representation::Tagged();
+ } else {
+ switch (op_) {
+#define SIMD_BINARY_OPERATION_CASE_ITEM(p1, p2, name, p4, left_representation, \
+ right_representation) \
+ case k##name: \
+ return index == 1 ? Representation::left_representation() \
+ : Representation::right_representation(); \
+ break;
+SIMD_BINARY_OPERATIONS(SIMD_BINARY_OPERATION_CASE_ITEM)
+#undef SIMD_BINARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return Representation::None();
+ }
+ }
+ }
+
+ BuiltinFunctionId op() const { return op_; }
+ const char* OpName() const;
+
+ DECLARE_CONCRETE_INSTRUCTION(BinarySIMDOperation)
+
+ protected:
+ virtual bool DataEquals(HValue* other) V8_OVERRIDE {
+ HBinarySIMDOperation* b = HBinarySIMDOperation::cast(other);
+ return op_ == b->op();
+ }
+
+ private:
+ HBinarySIMDOperation(HValue* context, HValue* left, HValue* right,
+ BuiltinFunctionId op)
+ : HTemplateInstruction<3>(HType::None()), op_(op) {
+ SetOperandAt(0, context);
+ SetOperandAt(1, left);
+ SetOperandAt(2, right);
+ switch (op) {
+#define SIMD_BINARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5, p6) \
+ case k##name: \
+ set_representation(Representation::representation()); \
+ set_type(HType::TypeFromRepresentation(representation_)); \
+ break;
+SIMD_BINARY_OPERATIONS(SIMD_BINARY_OPERATION_CASE_ITEM)
+#undef SIMD_BINARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ }
+ SetFlag(kUseGVN);
+ }
+
+ virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+
+ BuiltinFunctionId op_;
+};
+
+
+class HTernarySIMDOperation V8_FINAL : public HTemplateInstruction<4> {
+ public:
+ static HInstruction* New(Zone* zone,
+ HValue* context,
+ HValue* first,
+ HValue* second,
+ HValue* third,
+ BuiltinFunctionId op);
+
+ HValue* context() { return OperandAt(0); }
+ HValue* first() { return OperandAt(1); }
+ HValue* second() { return OperandAt(2); }
+ HValue* third() { return OperandAt(3); }
+
+ virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+
+ virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
+ if (index == 0) {
+ return Representation::Tagged();
+ } else {
+ switch (op_) {
+#define SIMD_TERNARY_OPERATION_CASE_ITEM(p1, p2, name, p4, \
+ first_representation, second_representation, third_representation) \
+ case k##name: \
+ switch (index) { \
+ case 1: return Representation::first_representation(); \
+ case 2: return Representation::second_representation(); \
+ case 3: return Representation::third_representation(); \
+ default: \
+ UNREACHABLE(); \
+ return Representation::None(); \
+ }
+SIMD_TERNARY_OPERATIONS(SIMD_TERNARY_OPERATION_CASE_ITEM)
+#undef SIMD_TERNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return Representation::None();
+ }
+ }
+ }
+
+ BuiltinFunctionId op() const { return op_; }
+ const char* OpName() const;
+
+ DECLARE_CONCRETE_INSTRUCTION(TernarySIMDOperation)
+
+ protected:
+ virtual bool DataEquals(HValue* other) V8_OVERRIDE {
+ HTernarySIMDOperation* b = HTernarySIMDOperation::cast(other);
+ return op_ == b->op();
+ }
+
+ private:
+ HTernarySIMDOperation(HValue* context, HValue* first, HValue* second,
+ HValue* third, BuiltinFunctionId op)
+ : HTemplateInstruction<4>(HType::None()), op_(op) {
+ SetOperandAt(0, context);
+ SetOperandAt(1, first);
+ SetOperandAt(2, second);
+ SetOperandAt(3, third);
+ switch (op) {
+#define SIMD_TERNARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5, \
+ p6, p7) \
+ case k##name: \
+ set_representation(Representation::representation()); \
+ set_type(HType::TypeFromRepresentation(representation_)); \
+ break;
+SIMD_TERNARY_OPERATIONS(SIMD_TERNARY_OPERATION_CASE_ITEM)
+#undef SIMD_TERNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ }
+ SetFlag(kUseGVN);
+ }
+
+ virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+
+ BuiltinFunctionId op_;
+};
+
+
+class HQuarternarySIMDOperation V8_FINAL : public HTemplateInstruction<5> {
+ public:
+ static HInstruction* New(Zone* zone,
+ HValue* context,
+ HValue* x,
+ HValue* y,
+ HValue* z,
+ HValue* w,
+ BuiltinFunctionId op);
+
+ HValue* context() { return OperandAt(0); }
+ HValue* x() { return OperandAt(1); }
+ HValue* y() { return OperandAt(2); }
+ HValue* z() { return OperandAt(3); }
+ HValue* w() { return OperandAt(4); }
+
+ virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+
+ virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
+ if (index == 0) {
+ return Representation::Tagged();
+ } else {
+ switch (op_) {
+#define SIMD_QUARTERNARY_OPERATION_CASE_ITEM(p1, p2, name, p4, \
+ first_representation, second_representation, third_representation, \
+ fourth_representation) \
+ case k##name: \
+ switch (index) { \
+ case 1: return Representation::first_representation(); \
+ case 2: return Representation::second_representation(); \
+ case 3: return Representation::third_representation(); \
+ case 4: return Representation::fourth_representation(); \
+ default: \
+ UNREACHABLE(); \
+ return Representation::None(); \
+ }
+SIMD_QUARTERNARY_OPERATIONS(SIMD_QUARTERNARY_OPERATION_CASE_ITEM)
+#undef SIMD_QUARTERNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return Representation::None();
+ }
+ }
+ }
+
+ BuiltinFunctionId op() const { return op_; }
+ const char* OpName() const;
+
+ DECLARE_CONCRETE_INSTRUCTION(QuarternarySIMDOperation)
+
+ protected:
+ virtual bool DataEquals(HValue* other) V8_OVERRIDE {
+ HQuarternarySIMDOperation* b = HQuarternarySIMDOperation::cast(other);
+ return op_ == b->op();
+ }
+
+ private:
+ HQuarternarySIMDOperation(HValue* context, HValue* x, HValue* y, HValue* z,
+ HValue* w, BuiltinFunctionId op)
+ : HTemplateInstruction<5>(HType::None()), op_(op) {
+ SetOperandAt(0, context);
+ SetOperandAt(1, x);
+ SetOperandAt(2, y);
+ SetOperandAt(3, z);
+ SetOperandAt(4, w);
+ switch (op) {
+#define SIMD_QUARTERNARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5, \
+ p6, p7, p8) \
+ case k##name: \
+ set_representation(Representation::representation()); \
+ set_type(HType::TypeFromRepresentation(representation_)); \
+ break;
+SIMD_QUARTERNARY_OPERATIONS(SIMD_QUARTERNARY_OPERATION_CASE_ITEM)
+#undef SIMD_QUARTERNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ }
+ SetFlag(kUseGVN);
+ }
+
+ virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+
+ BuiltinFunctionId op_;
+};
+
+
#undef DECLARE_INSTRUCTION
#undef DECLARE_CONCRETE_INSTRUCTION