Turn ElementsTransitionAndStore stub into a HydrogenCodeStub.
R=danno@chromium.org, mvstanton@chromium.org Review URL: https://codereview.chromium.org/18881004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15635 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9b856d724d
commit
6c13f097d6
@ -258,6 +258,17 @@ void StoreGlobalStub::InitializeInterfaceDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
|
||||||
|
Isolate* isolate,
|
||||||
|
CodeStubInterfaceDescriptor* descriptor) {
|
||||||
|
static Register registers[] = { r0, r3, r1, r2 };
|
||||||
|
descriptor->register_param_count_ = 4;
|
||||||
|
descriptor->register_params_ = registers;
|
||||||
|
descriptor->deoptimization_handler_ =
|
||||||
|
FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define __ ACCESS_MASM(masm)
|
#define __ ACCESS_MASM(masm)
|
||||||
|
|
||||||
|
|
||||||
|
@ -909,4 +909,75 @@ Handle<Code> StoreGlobalStub::GenerateCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
HValue* CodeStubGraphBuilder<ElementsTransitionAndStoreStub>::BuildCodeStub() {
|
||||||
|
ElementsTransitionAndStoreStub* stub = casted_stub();
|
||||||
|
ElementsKind from_kind = stub->from();
|
||||||
|
ElementsKind to_kind = stub->to();
|
||||||
|
|
||||||
|
HValue* value = GetParameter(0);
|
||||||
|
HValue* target_map = GetParameter(1);
|
||||||
|
HValue* key = GetParameter(2);
|
||||||
|
HValue* object = GetParameter(3);
|
||||||
|
|
||||||
|
if (FLAG_trace_elements_transitions) {
|
||||||
|
// Tracing elements transitions is the job of the runtime.
|
||||||
|
current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
|
||||||
|
set_current_block(NULL);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
info()->MarkAsSavesCallerDoubles();
|
||||||
|
|
||||||
|
if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
|
||||||
|
Add<HTrapAllocationMemento>(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we need to transition the array elements first
|
||||||
|
// (either SMI -> Double or Double -> Object).
|
||||||
|
if (DoesTransitionChangeElementsBufferFormat(from_kind, to_kind)) {
|
||||||
|
HInstruction* array_length = NULL;
|
||||||
|
if (stub->is_jsarray()) {
|
||||||
|
array_length = AddLoad(object, HObjectAccess::ForArrayLength());
|
||||||
|
} else {
|
||||||
|
array_length = AddLoadFixedArrayLength(AddLoadElements(object));
|
||||||
|
}
|
||||||
|
array_length->set_type(HType::Smi());
|
||||||
|
|
||||||
|
IfBuilder if_builder(this);
|
||||||
|
|
||||||
|
// Check if we have any elements.
|
||||||
|
if_builder.IfNot<HCompareNumericAndBranch>(array_length,
|
||||||
|
graph()->GetConstant0(),
|
||||||
|
Token::EQ);
|
||||||
|
if_builder.Then();
|
||||||
|
|
||||||
|
HInstruction* elements = AddLoadElements(object);
|
||||||
|
|
||||||
|
HInstruction* elements_length = AddLoadFixedArrayLength(elements);
|
||||||
|
|
||||||
|
BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
|
||||||
|
array_length, elements_length);
|
||||||
|
|
||||||
|
if_builder.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set transitioned map.
|
||||||
|
AddStore(object, HObjectAccess::ForMap(), target_map);
|
||||||
|
|
||||||
|
// Generate the actual store.
|
||||||
|
BuildUncheckedMonomorphicElementAccess(object, key, value, NULL,
|
||||||
|
stub->is_jsarray(), to_kind,
|
||||||
|
true, ALLOW_RETURN_HOLE,
|
||||||
|
stub->store_mode());
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() {
|
||||||
|
return DoGenerateCode(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
@ -811,44 +811,6 @@ bool ToBooleanStub::Types::CanBeUndetectable() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ElementsTransitionAndStoreStub::Generate(MacroAssembler* masm) {
|
|
||||||
Label fail;
|
|
||||||
AllocationSiteMode mode = AllocationSite::GetMode(from_, to_);
|
|
||||||
ASSERT(!IsFastHoleyElementsKind(from_) || IsFastHoleyElementsKind(to_));
|
|
||||||
if (!FLAG_trace_elements_transitions) {
|
|
||||||
if (IsFastSmiOrObjectElementsKind(to_)) {
|
|
||||||
if (IsFastSmiOrObjectElementsKind(from_)) {
|
|
||||||
ElementsTransitionGenerator::
|
|
||||||
GenerateMapChangeElementsTransition(masm, mode, &fail);
|
|
||||||
} else if (IsFastDoubleElementsKind(from_)) {
|
|
||||||
ASSERT(!IsFastSmiElementsKind(to_));
|
|
||||||
ElementsTransitionGenerator::GenerateDoubleToObject(masm, mode, &fail);
|
|
||||||
} else {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
KeyedStoreStubCompiler::GenerateStoreFastElement(masm,
|
|
||||||
is_jsarray_,
|
|
||||||
to_,
|
|
||||||
store_mode_);
|
|
||||||
} else if (IsFastSmiElementsKind(from_) &&
|
|
||||||
IsFastDoubleElementsKind(to_)) {
|
|
||||||
ElementsTransitionGenerator::GenerateSmiToDouble(masm, mode, &fail);
|
|
||||||
KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm,
|
|
||||||
is_jsarray_,
|
|
||||||
store_mode_);
|
|
||||||
} else if (IsFastDoubleElementsKind(from_)) {
|
|
||||||
ASSERT(to_ == FAST_HOLEY_DOUBLE_ELEMENTS);
|
|
||||||
ElementsTransitionGenerator::
|
|
||||||
GenerateMapChangeElementsTransition(masm, mode, &fail);
|
|
||||||
} else {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
masm->bind(&fail);
|
|
||||||
KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
|
void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
|
||||||
StubFailureTrampolineStub stub1(NOT_JS_FUNCTION_STUB_MODE);
|
StubFailureTrampolineStub stub1(NOT_JS_FUNCTION_STUB_MODE);
|
||||||
StubFailureTrampolineStub stub2(JS_FUNCTION_STUB_MODE);
|
StubFailureTrampolineStub stub2(JS_FUNCTION_STUB_MODE);
|
||||||
|
@ -2210,41 +2210,47 @@ class ToBooleanStub: public HydrogenCodeStub {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ElementsTransitionAndStoreStub : public PlatformCodeStub {
|
class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
|
||||||
public:
|
public:
|
||||||
ElementsTransitionAndStoreStub(ElementsKind from,
|
ElementsTransitionAndStoreStub(ElementsKind from,
|
||||||
ElementsKind to,
|
ElementsKind to,
|
||||||
bool is_jsarray,
|
bool is_jsarray,
|
||||||
StrictModeFlag strict_mode,
|
|
||||||
KeyedAccessStoreMode store_mode)
|
KeyedAccessStoreMode store_mode)
|
||||||
: from_(from),
|
: from_(from),
|
||||||
to_(to),
|
to_(to),
|
||||||
is_jsarray_(is_jsarray),
|
is_jsarray_(is_jsarray),
|
||||||
strict_mode_(strict_mode),
|
store_mode_(store_mode) {
|
||||||
store_mode_(store_mode) {}
|
ASSERT(!IsFastHoleyElementsKind(from) || IsFastHoleyElementsKind(to));
|
||||||
|
|
||||||
private:
|
|
||||||
class FromBits: public BitField<ElementsKind, 0, 8> {};
|
|
||||||
class ToBits: public BitField<ElementsKind, 8, 8> {};
|
|
||||||
class IsJSArrayBits: public BitField<bool, 16, 1> {};
|
|
||||||
class StrictModeBits: public BitField<StrictModeFlag, 17, 1> {};
|
|
||||||
class StoreModeBits: public BitField<KeyedAccessStoreMode, 18, 4> {};
|
|
||||||
|
|
||||||
Major MajorKey() { return ElementsTransitionAndStore; }
|
|
||||||
int MinorKey() {
|
|
||||||
return FromBits::encode(from_) |
|
|
||||||
ToBits::encode(to_) |
|
|
||||||
IsJSArrayBits::encode(is_jsarray_) |
|
|
||||||
StrictModeBits::encode(strict_mode_) |
|
|
||||||
StoreModeBits::encode(store_mode_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Generate(MacroAssembler* masm);
|
ElementsKind from() const { return from_; }
|
||||||
|
ElementsKind to() const { return to_; }
|
||||||
|
bool is_jsarray() const { return is_jsarray_; }
|
||||||
|
KeyedAccessStoreMode store_mode() const { return store_mode_; }
|
||||||
|
|
||||||
|
Handle<Code> GenerateCode();
|
||||||
|
|
||||||
|
void InitializeInterfaceDescriptor(
|
||||||
|
Isolate* isolate,
|
||||||
|
CodeStubInterfaceDescriptor* descriptor);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class FromBits: public BitField<ElementsKind, 0, 8> {};
|
||||||
|
class ToBits: public BitField<ElementsKind, 8, 8> {};
|
||||||
|
class IsJSArrayBits: public BitField<bool, 16, 1> {};
|
||||||
|
class StoreModeBits: public BitField<KeyedAccessStoreMode, 17, 4> {};
|
||||||
|
|
||||||
|
Major MajorKey() { return ElementsTransitionAndStore; }
|
||||||
|
int NotMissMinorKey() {
|
||||||
|
return FromBits::encode(from()) |
|
||||||
|
ToBits::encode(to()) |
|
||||||
|
IsJSArrayBits::encode(is_jsarray()) |
|
||||||
|
StoreModeBits::encode(store_mode());
|
||||||
|
}
|
||||||
|
|
||||||
ElementsKind from_;
|
ElementsKind from_;
|
||||||
ElementsKind to_;
|
ElementsKind to_;
|
||||||
bool is_jsarray_;
|
bool is_jsarray_;
|
||||||
StrictModeFlag strict_mode_;
|
|
||||||
KeyedAccessStoreMode store_mode_;
|
KeyedAccessStoreMode store_mode_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
|
DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
|
||||||
|
@ -229,6 +229,15 @@ inline bool CanTransitionToMoreGeneralFastElementsKind(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool DoesTransitionChangeElementsBufferFormat(ElementsKind from_kind,
|
||||||
|
ElementsKind to_kind) {
|
||||||
|
return (IsFastSmiElementsKind(from_kind) &&
|
||||||
|
IsFastDoubleElementsKind(to_kind)) ||
|
||||||
|
(IsFastDoubleElementsKind(from_kind) &&
|
||||||
|
IsFastObjectElementsKind(to_kind));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
|
||||||
#endif // V8_ELEMENTS_KIND_H_
|
#endif // V8_ELEMENTS_KIND_H_
|
||||||
|
@ -187,7 +187,7 @@ DEFINE_implication(harmony_observation, harmony_collections)
|
|||||||
// Flags for experimental implementation features.
|
// Flags for experimental implementation features.
|
||||||
DEFINE_bool(packed_arrays, true, "optimizes arrays that have no holes")
|
DEFINE_bool(packed_arrays, true, "optimizes arrays that have no holes")
|
||||||
DEFINE_bool(smi_only_arrays, true, "tracks arrays with only smi values")
|
DEFINE_bool(smi_only_arrays, true, "tracks arrays with only smi values")
|
||||||
DEFINE_bool(compiled_transitions, true, "use optimizing compiler to "
|
DEFINE_bool(compiled_transitions, false, "use optimizing compiler to "
|
||||||
"generate array elements transition stubs")
|
"generate array elements transition stubs")
|
||||||
DEFINE_bool(compiled_keyed_stores, true, "use optimizing compiler to "
|
DEFINE_bool(compiled_keyed_stores, true, "use optimizing compiler to "
|
||||||
"generate keyed store stubs")
|
"generate keyed store stubs")
|
||||||
|
@ -262,6 +262,17 @@ void StoreGlobalStub::InitializeInterfaceDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
|
||||||
|
Isolate* isolate,
|
||||||
|
CodeStubInterfaceDescriptor* descriptor) {
|
||||||
|
static Register registers[] = { eax, ebx, ecx, edx };
|
||||||
|
descriptor->register_param_count_ = 4;
|
||||||
|
descriptor->register_params_ = registers;
|
||||||
|
descriptor->deoptimization_handler_ =
|
||||||
|
FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define __ ACCESS_MASM(masm)
|
#define __ ACCESS_MASM(masm)
|
||||||
|
|
||||||
|
|
||||||
|
18
src/ic.cc
18
src/ic.cc
@ -2476,6 +2476,24 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) {
|
||||||
|
SealHandleScope scope(isolate);
|
||||||
|
ASSERT(args.length() == 4);
|
||||||
|
KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
|
||||||
|
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
|
||||||
|
Handle<Object> value = args.at<Object>(0);
|
||||||
|
Handle<Object> key = args.at<Object>(2);
|
||||||
|
Handle<Object> object = args.at<Object>(3);
|
||||||
|
StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state);
|
||||||
|
return Runtime::SetObjectProperty(isolate,
|
||||||
|
object,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
NONE,
|
||||||
|
strict_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void BinaryOpIC::patch(Code* code) {
|
void BinaryOpIC::patch(Code* code) {
|
||||||
set_target(code);
|
set_target(code);
|
||||||
}
|
}
|
||||||
|
1
src/ic.h
1
src/ic.h
@ -858,6 +858,7 @@ DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
|
|||||||
DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
|
DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
|
||||||
DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss);
|
DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss);
|
||||||
DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure);
|
DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure);
|
||||||
|
DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss);
|
||||||
DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
|
DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
|
||||||
DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss);
|
DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss);
|
||||||
|
|
||||||
|
@ -259,6 +259,17 @@ void StoreGlobalStub::InitializeInterfaceDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
|
||||||
|
Isolate* isolate,
|
||||||
|
CodeStubInterfaceDescriptor* descriptor) {
|
||||||
|
static Register registers[] = { a0, a3, a1, a2 };
|
||||||
|
descriptor->register_param_count_ = 4;
|
||||||
|
descriptor->register_params_ = registers;
|
||||||
|
descriptor->deoptimization_handler_ =
|
||||||
|
FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define __ ACCESS_MASM(masm)
|
#define __ ACCESS_MASM(masm)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1997,7 +1997,6 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
|
|||||||
elements_kind,
|
elements_kind,
|
||||||
transitioned_map->elements_kind(),
|
transitioned_map->elements_kind(),
|
||||||
is_js_array,
|
is_js_array,
|
||||||
strict_mode(),
|
|
||||||
store_mode_).GetCode(isolate());
|
store_mode_).GetCode(isolate());
|
||||||
} else {
|
} else {
|
||||||
if (FLAG_compiled_keyed_stores &&
|
if (FLAG_compiled_keyed_stores &&
|
||||||
|
@ -258,6 +258,17 @@ void StoreGlobalStub::InitializeInterfaceDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
|
||||||
|
Isolate* isolate,
|
||||||
|
CodeStubInterfaceDescriptor* descriptor) {
|
||||||
|
static Register registers[] = { rax, rbx, rcx, rdx };
|
||||||
|
descriptor->register_param_count_ = 4;
|
||||||
|
descriptor->register_params_ = registers;
|
||||||
|
descriptor->deoptimization_handler_ =
|
||||||
|
FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define __ ACCESS_MASM(masm)
|
#define __ ACCESS_MASM(masm)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user