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)
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
StubFailureTrampolineStub stub1(NOT_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:
|
||||
ElementsTransitionAndStoreStub(ElementsKind from,
|
||||
ElementsKind to,
|
||||
bool is_jsarray,
|
||||
StrictModeFlag strict_mode,
|
||||
KeyedAccessStoreMode store_mode)
|
||||
: from_(from),
|
||||
to_(to),
|
||||
is_jsarray_(is_jsarray),
|
||||
strict_mode_(strict_mode),
|
||||
store_mode_(store_mode) {}
|
||||
|
||||
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_);
|
||||
store_mode_(store_mode) {
|
||||
ASSERT(!IsFastHoleyElementsKind(from) || IsFastHoleyElementsKind(to));
|
||||
}
|
||||
|
||||
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 to_;
|
||||
bool is_jsarray_;
|
||||
StrictModeFlag strict_mode_;
|
||||
KeyedAccessStoreMode store_mode_;
|
||||
|
||||
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
|
||||
|
||||
#endif // V8_ELEMENTS_KIND_H_
|
||||
|
@ -187,7 +187,7 @@ DEFINE_implication(harmony_observation, harmony_collections)
|
||||
// Flags for experimental implementation features.
|
||||
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(compiled_transitions, true, "use optimizing compiler to "
|
||||
DEFINE_bool(compiled_transitions, false, "use optimizing compiler to "
|
||||
"generate array elements transition stubs")
|
||||
DEFINE_bool(compiled_keyed_stores, true, "use optimizing compiler to "
|
||||
"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)
|
||||
|
||||
|
||||
|
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) {
|
||||
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*, UnaryOpIC_Miss);
|
||||
DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure);
|
||||
DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss);
|
||||
DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_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)
|
||||
|
||||
|
||||
|
@ -1997,7 +1997,6 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
|
||||
elements_kind,
|
||||
transitioned_map->elements_kind(),
|
||||
is_js_array,
|
||||
strict_mode(),
|
||||
store_mode_).GetCode(isolate());
|
||||
} else {
|
||||
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)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user