Commit a9fd01d5 authored by verwaest@chromium.org's avatar verwaest@chromium.org

- Makes a common superclass for Load and Store stub compiler.

- Splits all non-normal Store ICs into handler and IC.
- Ensures monomorphic store ICs go polymorphic.
- Feeds polymorphic type feedback into count operation.

R=ulan@chromium.org

Review URL: https://chromiumcodereview.appspot.com/14142005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15566 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c2b03997
......@@ -3403,7 +3403,8 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss);
__ bind(&miss);
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
StubCompiler::TailCallBuiltin(
masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
}
......@@ -3434,7 +3435,8 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
support_wrapper_);
__ bind(&miss);
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
StubCompiler::TailCallBuiltin(
masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
}
......@@ -3504,7 +3506,8 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
__ bind(&miss);
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
StubCompiler::TailCallBuiltin(
masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
}
......
......@@ -1531,8 +1531,9 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
// -----------------------------------
// Get the receiver from the stack and probe the stub cache.
Code::Flags flags =
Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC, strict_mode);
Code::Flags flags = Code::ComputeFlags(
Code::STUB, MONOMORPHIC, strict_mode,
Code::NORMAL, Code::STORE_IC);
Isolate::Current()->stub_cache()->GenerateProbe(
masm, flags, r1, r2, r3, r4, r5, r6);
......
This diff is collapsed.
......@@ -503,7 +503,7 @@ void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle,
// Record receiver type for monomorphic keyed stores.
receiver_types_.Add(oracle->StoreMonomorphicReceiverType(id), zone);
store_mode_ = oracle->GetStoreMode(id);
} else if (oracle->StoreIsPolymorphic(id)) {
} else if (oracle->StoreIsKeyedPolymorphic(id)) {
receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
oracle->CollectKeyedReceiverTypes(id, &receiver_types_);
store_mode_ = oracle->GetStoreMode(id);
......@@ -520,9 +520,11 @@ void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle,
// Record receiver type for monomorphic keyed stores.
receiver_types_.Add(
oracle->StoreMonomorphicReceiverType(id), zone);
} else if (oracle->StoreIsPolymorphic(id)) {
} else if (oracle->StoreIsKeyedPolymorphic(id)) {
receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
oracle->CollectKeyedReceiverTypes(id, &receiver_types_);
} else {
oracle->CollectPolymorphicStoreReceiverTypes(id, &receiver_types_);
}
store_mode_ = oracle->GetStoreMode(id);
type_ = oracle->IncrementType(this);
......
......@@ -2910,7 +2910,8 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss);
__ bind(&miss);
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
StubCompiler::TailCallBuiltin(
masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
}
......@@ -2930,7 +2931,8 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss,
support_wrapper_);
__ bind(&miss);
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
StubCompiler::TailCallBuiltin(
masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
}
......@@ -2994,7 +2996,8 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
__ bind(&miss);
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
StubCompiler::TailCallBuiltin(
masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
}
......
......@@ -1421,8 +1421,9 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
// -- esp[0] : return address
// -----------------------------------
Code::Flags flags =
Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC, strict_mode);
Code::Flags flags = Code::ComputeFlags(
Code::STUB, MONOMORPHIC, strict_mode,
Code::NORMAL, Code::STORE_IC);
Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
no_reg);
......
This diff is collapsed.
......@@ -217,9 +217,11 @@ static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
int index = map->IndexInCodeCache(name, target);
if (index >= 0) {
map->RemoveFromCodeCache(String::cast(name), target, index);
// For loads, handlers are stored in addition to the ICs on the map. Remove
// those, too.
if (target->is_load_stub() || target->is_keyed_load_stub()) {
// For loads and stores, handlers are stored in addition to the ICs on the
// map. Remove those, too.
if ((target->is_load_stub() || target->is_keyed_load_stub() ||
target->is_store_stub() || target->is_keyed_store_stub()) &&
target->type() != Code::NORMAL) {
Code* handler = target->FindFirstCode();
index = map->IndexInCodeCache(name, handler);
if (index >= 0) {
......@@ -972,10 +974,10 @@ static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
bool IC::UpdatePolymorphicIC(State state,
StrictModeFlag strict_mode,
Handle<JSObject> receiver,
Handle<String> name,
Handle<Code> code) {
Handle<Code> code,
StrictModeFlag strict_mode) {
if (code->type() == Code::NORMAL) return false;
if (target()->ic_state() == MONOMORPHIC &&
target()->type() == Code::NORMAL) {
......@@ -1026,18 +1028,39 @@ bool IC::UpdatePolymorphicIC(State state,
handlers.Add(code);
}
Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
&receiver_maps, &handlers, number_of_valid_maps, name);
Handle<Code> ic = ComputePolymorphicIC(
&receiver_maps, &handlers, number_of_valid_maps, name, strict_mode);
set_target(*ic);
return true;
}
Handle<Code> LoadIC::ComputePolymorphicIC(MapHandleList* receiver_maps,
CodeHandleList* handlers,
int number_of_valid_maps,
Handle<Name> name,
StrictModeFlag strict_mode) {
return isolate()->stub_cache()->ComputePolymorphicLoadIC(
receiver_maps, handlers, number_of_valid_maps, name);
}
Handle<Code> StoreIC::ComputePolymorphicIC(MapHandleList* receiver_maps,
CodeHandleList* handlers,
int number_of_valid_maps,
Handle<Name> name,
StrictModeFlag strict_mode) {
return isolate()->stub_cache()->ComputePolymorphicStoreIC(
receiver_maps, handlers, number_of_valid_maps, name, strict_mode);
}
void LoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
Handle<String> name) {
Handle<String> name,
StrictModeFlag strict_mode) {
if (handler->type() == Code::NORMAL) return set_target(*handler);
Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicLoadIC(
receiver, handler, name);
set_target(*ic);
}
......@@ -1045,14 +1068,37 @@ void LoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
void KeyedLoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
Handle<String> name) {
Handle<String> name,
StrictModeFlag strict_mode) {
if (handler->type() == Code::NORMAL) return set_target(*handler);
Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedMonomorphicIC(
Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedLoadIC(
receiver, handler, name);
set_target(*ic);
}
void StoreIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
Handle<String> name,
StrictModeFlag strict_mode) {
if (handler->type() == Code::NORMAL) return set_target(*handler);
Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicStoreIC(
receiver, handler, name, strict_mode);
set_target(*ic);
}
void KeyedStoreIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
Handle<String> name,
StrictModeFlag strict_mode) {
if (handler->type() == Code::NORMAL) return set_target(*handler);
Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedStoreIC(
receiver, handler, name, strict_mode);
set_target(*ic);
}
void IC::CopyICToMegamorphicCache(Handle<String> name) {
MapHandleList receiver_maps;
CodeHandleList handlers;
......@@ -1094,12 +1140,12 @@ void IC::PatchCache(State state,
case UNINITIALIZED:
case PREMONOMORPHIC:
case MONOMORPHIC_PROTOTYPE_FAILURE:
UpdateMonomorphicIC(receiver, code, name);
UpdateMonomorphicIC(receiver, code, name, strict_mode);
break;
case MONOMORPHIC:
// Only move to megamorphic if the target changes.
if (target() != *code) {
if (target()->is_load_stub()) {
if (target()->is_load_stub() || target()->is_store_stub()) {
bool is_same_handler = false;
{
DisallowHeapAllocation no_allocation;
......@@ -1108,10 +1154,10 @@ void IC::PatchCache(State state,
}
if (is_same_handler
&& IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
UpdateMonomorphicIC(receiver, code, name);
UpdateMonomorphicIC(receiver, code, name, strict_mode);
break;
}
if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) {
if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) {
break;
}
......@@ -1131,13 +1177,15 @@ void IC::PatchCache(State state,
UpdateMegamorphicCache(receiver->map(), *name, *code);
break;
case POLYMORPHIC:
if (target()->is_load_stub()) {
if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) {
if (target()->is_load_stub() || target()->is_store_stub()) {
if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) {
break;
}
CopyICToMegamorphicCache(name);
UpdateMegamorphicCache(receiver->map(), *name, *code);
set_target(*megamorphic_stub());
set_target((strict_mode == kStrictMode)
? *megamorphic_stub_strict()
: *megamorphic_stub());
} else {
// When trying to patch a polymorphic keyed load/store element stub
// with anything other than another polymorphic stub, go generic.
......
......@@ -169,14 +169,25 @@ class IC {
virtual void UpdateMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
Handle<String> name) {
Handle<String> name,
StrictModeFlag strict_mode) {
set_target(*handler);
}
bool UpdatePolymorphicIC(State state,
StrictModeFlag strict_mode,
Handle<JSObject> receiver,
Handle<String> name,
Handle<Code> code);
Handle<Code> code,
StrictModeFlag strict_mode);
virtual Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps,
CodeHandleList* handlers,
int number_of_valid_maps,
Handle<Name> name,
StrictModeFlag strict_mode) {
UNREACHABLE();
return Handle<Code>::null();
};
void CopyICToMegamorphicCache(Handle<String> name);
bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map);
void PatchCache(State state,
......@@ -391,9 +402,18 @@ class LoadIC: public IC {
State state,
Handle<Object> object,
Handle<String> name);
virtual void UpdateMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
Handle<String> name);
Handle<String> name,
StrictModeFlag strict_mode);
virtual Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps,
CodeHandleList* handlers,
int number_of_valid_maps,
Handle<Name> name,
StrictModeFlag strict_mode);
virtual Handle<Code> ComputeLoadHandler(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<String> name);
......@@ -467,7 +487,8 @@ class KeyedLoadIC: public LoadIC {
// Update the inline cache.
virtual void UpdateMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
Handle<String> name);
Handle<String> name,
StrictModeFlag strict_mode);
virtual Handle<Code> ComputeLoadHandler(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<String> name);
......@@ -544,6 +565,16 @@ class StoreIC: public IC {
return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
}
virtual void UpdateMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
Handle<String> name,
StrictModeFlag strict_mode);
virtual Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps,
CodeHandleList* handlers,
int number_of_valid_maps,
Handle<Name> name,
StrictModeFlag strict_mode);
// Update the inline cache and the global stub cache based on the
// lookup result.
......@@ -642,6 +673,11 @@ class KeyedStoreIC: public StoreIC {
KeyedAccessStoreMode store_mode,
StrictModeFlag strict_mode);
virtual void UpdateMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
Handle<String> name,
StrictModeFlag strict_mode);
private:
void set_target(Code* code) {
// Strict mode must be preserved across IC patching.
......
This diff is collapsed.
This diff is collapsed.
......@@ -170,14 +170,14 @@ bool TypeFeedbackOracle::StoreIsMonomorphicNormal(TypeFeedbackId ast_id) {
}
bool TypeFeedbackOracle::StoreIsPolymorphic(TypeFeedbackId ast_id) {
bool TypeFeedbackOracle::StoreIsKeyedPolymorphic(TypeFeedbackId ast_id) {
Handle<Object> map_or_code = GetInfo(ast_id);
if (map_or_code->IsCode()) {
Handle<Code> code = Handle<Code>::cast(map_or_code);
bool standard_store = FLAG_compiled_keyed_stores ||
(Code::GetKeyedAccessStoreMode(code->extra_ic_state()) ==
STANDARD_STORE);
return code->is_keyed_store_stub() && standard_store &&
return code->is_keyed_store_stub() && standard_store &&
code->ic_state() == POLYMORPHIC;
}
return false;
......@@ -267,7 +267,9 @@ void TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
void TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
Handle<String> name,
SmallMapList* types) {
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC);
Code::Flags flags = Code::ComputeFlags(
Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
Code::NORMAL, Code::STORE_IC);
CollectReceiverTypes(expr->AssignmentFeedbackId(), name, flags, types);
}
......@@ -551,6 +553,18 @@ void TypeFeedbackOracle::CollectKeyedReceiverTypes(TypeFeedbackId ast_id,
}
void TypeFeedbackOracle::CollectPolymorphicStoreReceiverTypes(
TypeFeedbackId ast_id,
SmallMapList* types) {
Handle<Object> object = GetInfo(ast_id);
if (!object->IsCode()) return;
Handle<Code> code = Handle<Code>::cast(object);
if (code->kind() == Code::STORE_IC && code->ic_state() == POLYMORPHIC) {
CollectPolymorphicMaps(code, types);
}
}
byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) {
Handle<Object> object = GetInfo(id);
return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0;
......
......@@ -246,7 +246,7 @@ class TypeFeedbackOracle: public ZoneObject {
bool LoadIsPolymorphic(Property* expr);
bool StoreIsUninitialized(TypeFeedbackId ast_id);
bool StoreIsMonomorphicNormal(TypeFeedbackId ast_id);
bool StoreIsPolymorphic(TypeFeedbackId ast_id);
bool StoreIsKeyedPolymorphic(TypeFeedbackId ast_id);
bool CallIsMonomorphic(Call* expr);
bool CallNewIsMonomorphic(CallNew* expr);
bool ObjectLiteralStoreIsMonomorphic(ObjectLiteralProperty* prop);
......@@ -272,6 +272,8 @@ class TypeFeedbackOracle: public ZoneObject {
SmallMapList* types);
void CollectKeyedReceiverTypes(TypeFeedbackId ast_id,
SmallMapList* types);
void CollectPolymorphicStoreReceiverTypes(TypeFeedbackId ast_id,
SmallMapList* types);
static bool CanRetainOtherContext(Map* map, Context* native_context);
static bool CanRetainOtherContext(JSFunction* function,
......
......@@ -2045,7 +2045,8 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss);
__ bind(&miss);
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
StubCompiler::TailCallBuiltin(
masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
}
......@@ -2074,7 +2075,8 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss,
support_wrapper_);
__ bind(&miss);
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
StubCompiler::TailCallBuiltin(
masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
}
......@@ -2137,7 +2139,8 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
__ bind(&miss);
StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
StubCompiler::TailCallBuiltin(
masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
}
......
......@@ -1449,8 +1449,9 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
// -----------------------------------
// Get the receiver from the stack and probe the stub cache.
Code::Flags flags =
Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC, strict_mode);
Code::Flags flags = Code::ComputeFlags(
Code::STUB, MONOMORPHIC, strict_mode,
Code::NORMAL, Code::STORE_IC);
Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
no_reg);
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment