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

Replace miss_mode flag with explicit Load/Store Force Generic methods.

R=ishell@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17774 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 14a25f1e
...@@ -1346,9 +1346,14 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { ...@@ -1346,9 +1346,14 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
} }
MaybeObject* KeyedLoadIC::Load(Handle<Object> object, MaybeObject* KeyedLoadIC::LoadForceGeneric(Handle<Object> object,
Handle<Object> key, Handle<Object> key) {
ICMissMode miss_mode) { set_target(*generic_stub());
return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
}
MaybeObject* KeyedLoadIC::Load(Handle<Object> object, Handle<Object> key) {
if (MigrateDeprecated(object)) { if (MigrateDeprecated(object)) {
return Runtime::GetObjectPropertyOrFail(isolate(), object, key); return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
} }
...@@ -1365,20 +1370,18 @@ MaybeObject* KeyedLoadIC::Load(Handle<Object> object, ...@@ -1365,20 +1370,18 @@ MaybeObject* KeyedLoadIC::Load(Handle<Object> object,
if (maybe_object->IsFailure()) return maybe_object; if (maybe_object->IsFailure()) return maybe_object;
} else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
ASSERT(!object->IsJSGlobalProxy()); ASSERT(!object->IsJSGlobalProxy());
if (miss_mode != MISS_FORCE_GENERIC) { if (object->IsString() && key->IsNumber()) {
if (object->IsString() && key->IsNumber()) { if (state() == UNINITIALIZED) stub = string_stub();
if (state() == UNINITIALIZED) stub = string_stub(); } else if (object->IsJSObject()) {
} else if (object->IsJSObject()) { Handle<JSObject> receiver = Handle<JSObject>::cast(object);
Handle<JSObject> receiver = Handle<JSObject>::cast(object); if (receiver->elements()->map() ==
if (receiver->elements()->map() == isolate()->heap()->non_strict_arguments_elements_map()) {
isolate()->heap()->non_strict_arguments_elements_map()) { stub = non_strict_arguments_stub();
stub = non_strict_arguments_stub(); } else if (receiver->HasIndexedInterceptor()) {
} else if (receiver->HasIndexedInterceptor()) { stub = indexed_interceptor_stub();
stub = indexed_interceptor_stub(); } else if (!key->ToSmi()->IsFailure() &&
} else if (!key->ToSmi()->IsFailure() && (!target().is_identical_to(non_strict_arguments_stub()))) {
(!target().is_identical_to(non_strict_arguments_stub()))) { stub = LoadElementStub(receiver);
stub = LoadElementStub(receiver);
}
} }
} }
} }
...@@ -1928,10 +1931,23 @@ KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver, ...@@ -1928,10 +1931,23 @@ KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
} }
MaybeObject* KeyedStoreIC::StoreForceGeneric(Handle<Object> object,
Handle<Object> key,
Handle<Object> value) {
set_target(*generic_stub());
Handle<Object> result = Runtime::SetObjectProperty(isolate(), object,
key,
value,
NONE,
strict_mode());
RETURN_IF_EMPTY_HANDLE(isolate(), result);
return *result;
}
MaybeObject* KeyedStoreIC::Store(Handle<Object> object, MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
Handle<Object> key, Handle<Object> key,
Handle<Object> value, Handle<Object> value) {
ICMissMode miss_mode) {
if (MigrateDeprecated(object)) { if (MigrateDeprecated(object)) {
Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, Handle<Object> result = Runtime::SetObjectProperty(isolate(), object,
key, key,
...@@ -1970,24 +1986,22 @@ MaybeObject* KeyedStoreIC::Store(Handle<Object> object, ...@@ -1970,24 +1986,22 @@ MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
if (use_ic) { if (use_ic) {
ASSERT(!object->IsJSGlobalProxy()); ASSERT(!object->IsJSGlobalProxy());
if (miss_mode != MISS_FORCE_GENERIC) { if (object->IsJSObject()) {
if (object->IsJSObject()) { Handle<JSObject> receiver = Handle<JSObject>::cast(object);
Handle<JSObject> receiver = Handle<JSObject>::cast(object); bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure();
bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); if (receiver->elements()->map() ==
if (receiver->elements()->map() == isolate()->heap()->non_strict_arguments_elements_map()) {
isolate()->heap()->non_strict_arguments_elements_map()) { stub = non_strict_arguments_stub();
stub = non_strict_arguments_stub(); } else if (key_is_smi_like &&
} else if (key_is_smi_like && !(target().is_identical_to(non_strict_arguments_stub()))) {
!(target().is_identical_to(non_strict_arguments_stub()))) { // We should go generic if receiver isn't a dictionary, but our
// We should go generic if receiver isn't a dictionary, but our // prototype chain does have dictionary elements. This ensures that
// prototype chain does have dictionary elements. This ensures that // other non-dictionary receivers in the polymorphic case benefit
// other non-dictionary receivers in the polymorphic case benefit // from fast path keyed stores.
// from fast path keyed stores. if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) {
if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { KeyedAccessStoreMode store_mode =
KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value);
GetStoreMode(receiver, key, value); stub = StoreElementStub(receiver, store_mode);
stub = StoreElementStub(receiver, store_mode);
}
} }
} }
} }
...@@ -2086,7 +2100,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { ...@@ -2086,7 +2100,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
Handle<Object> receiver = args.at<Object>(0); Handle<Object> receiver = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1); Handle<Object> key = args.at<Object>(1);
ic.UpdateState(receiver, key); ic.UpdateState(receiver, key);
return ic.Load(receiver, key, MISS); return ic.Load(receiver, key);
} }
...@@ -2097,7 +2111,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { ...@@ -2097,7 +2111,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) {
Handle<Object> receiver = args.at<Object>(0); Handle<Object> receiver = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1); Handle<Object> key = args.at<Object>(1);
ic.UpdateState(receiver, key); ic.UpdateState(receiver, key);
return ic.Load(receiver, key, MISS); return ic.Load(receiver, key);
} }
...@@ -2108,7 +2122,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { ...@@ -2108,7 +2122,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
Handle<Object> receiver = args.at<Object>(0); Handle<Object> receiver = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1); Handle<Object> key = args.at<Object>(1);
ic.UpdateState(receiver, key); ic.UpdateState(receiver, key);
return ic.Load(receiver, key, MISS_FORCE_GENERIC); return ic.LoadForceGeneric(receiver, key);
} }
...@@ -2217,7 +2231,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { ...@@ -2217,7 +2231,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
Handle<Object> receiver = args.at<Object>(0); Handle<Object> receiver = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1); Handle<Object> key = args.at<Object>(1);
ic.UpdateState(receiver, key); ic.UpdateState(receiver, key);
return ic.Store(receiver, key, args.at<Object>(2), MISS); return ic.Store(receiver, key, args.at<Object>(2));
} }
...@@ -2228,7 +2242,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { ...@@ -2228,7 +2242,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) {
Handle<Object> receiver = args.at<Object>(0); Handle<Object> receiver = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1); Handle<Object> key = args.at<Object>(1);
ic.UpdateState(receiver, key); ic.UpdateState(receiver, key);
return ic.Store(receiver, key, args.at<Object>(2), MISS); return ic.Store(receiver, key, args.at<Object>(2));
} }
...@@ -2273,7 +2287,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { ...@@ -2273,7 +2287,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
Handle<Object> receiver = args.at<Object>(0); Handle<Object> receiver = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1); Handle<Object> key = args.at<Object>(1);
ic.UpdateState(receiver, key); ic.UpdateState(receiver, key);
return ic.Store(receiver, key, args.at<Object>(2), MISS_FORCE_GENERIC); return ic.StoreForceGeneric(receiver, key, args.at<Object>(2));
} }
...@@ -2560,7 +2574,7 @@ CompareIC::State CompareIC::TargetState(State old_state, ...@@ -2560,7 +2574,7 @@ CompareIC::State CompareIC::TargetState(State old_state,
} }
void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
HandleScope scope(isolate()); HandleScope scope(isolate());
State previous_left, previous_right, previous_state; State previous_left, previous_right, previous_state;
ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left, ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left,
...@@ -2574,7 +2588,8 @@ void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { ...@@ -2574,7 +2588,8 @@ void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
stub.set_known_map( stub.set_known_map(
Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate()));
} }
set_target(*stub.GetCode(isolate())); Handle<Code> new_target = stub.GetCode(isolate());
set_target(*new_target);
#ifdef DEBUG #ifdef DEBUG
if (FLAG_trace_ic) { if (FLAG_trace_ic) {
...@@ -2596,6 +2611,8 @@ void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { ...@@ -2596,6 +2611,8 @@ void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
if (previous_state == UNINITIALIZED) { if (previous_state == UNINITIALIZED) {
PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
} }
return *new_target;
} }
...@@ -2604,8 +2621,7 @@ RUNTIME_FUNCTION(Code*, CompareIC_Miss) { ...@@ -2604,8 +2621,7 @@ RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
HandleScope scope(isolate); HandleScope scope(isolate);
ASSERT(args.length() == 3); ASSERT(args.length() == 3);
CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
return ic.raw_target();
} }
...@@ -2716,9 +2732,8 @@ Builtins::JavaScript BinaryOpIC::TokenToJSBuiltin(Token::Value op) { ...@@ -2716,9 +2732,8 @@ Builtins::JavaScript BinaryOpIC::TokenToJSBuiltin(Token::Value op) {
} }
MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object, MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object) {
Code::ExtraICState extra_ic_state) { ToBooleanStub stub(target()->extended_extra_ic_state());
ToBooleanStub stub(extra_ic_state);
bool to_boolean_value = stub.UpdateStatus(object); bool to_boolean_value = stub.UpdateStatus(object);
Handle<Code> code = stub.GetCode(isolate()); Handle<Code> code = stub.GetCode(isolate());
set_target(*code); set_target(*code);
...@@ -2731,8 +2746,7 @@ RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) { ...@@ -2731,8 +2746,7 @@ RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) {
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<Object> object = args.at<Object>(0); Handle<Object> object = args.at<Object>(0);
ToBooleanIC ic(isolate); ToBooleanIC ic(isolate);
Code::ExtraICState extra_ic_state = ic.target()->extended_extra_ic_state(); return ic.ToBoolean(object);
return ic.ToBoolean(object, extra_ic_state);
} }
......
...@@ -94,10 +94,6 @@ class IC { ...@@ -94,10 +94,6 @@ class IC {
IC(FrameDepth depth, Isolate* isolate); IC(FrameDepth depth, Isolate* isolate);
virtual ~IC() {} virtual ~IC() {}
// Get the call-site target; used for determining the state.
Handle<Code> target() const { return target_; }
Code* raw_target() const { return GetTargetAtAddress(address()); }
State state() const { return state_; } State state() const { return state_; }
inline Address address() const; inline Address address() const;
...@@ -130,6 +126,20 @@ class IC { ...@@ -130,6 +126,20 @@ class IC {
return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT; return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
} }
#ifdef DEBUG
bool IsLoadStub() {
return target()->is_load_stub() || target()->is_keyed_load_stub();
}
bool IsStoreStub() {
return target()->is_store_stub() || target()->is_keyed_store_stub();
}
bool IsCallStub() {
return target()->is_call_stub() || target()->is_keyed_call_stub();
}
#endif
// Determines which map must be used for keeping the code stub. // Determines which map must be used for keeping the code stub.
// These methods should not be called with undefined or null. // These methods should not be called with undefined or null.
static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object); static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object);
...@@ -146,6 +156,9 @@ class IC { ...@@ -146,6 +156,9 @@ class IC {
} }
protected: protected:
// Get the call-site target; used for determining the state.
Handle<Code> target() const { return target_; }
Address fp() const { return fp_; } Address fp() const { return fp_; }
Address pc() const { return *pc_address_; } Address pc() const { return *pc_address_; }
Isolate* isolate() const { return isolate_; } Isolate* isolate() const { return isolate_; }
...@@ -229,6 +242,8 @@ class IC { ...@@ -229,6 +242,8 @@ class IC {
void TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name); void TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name);
private: private:
Code* raw_target() const { return GetTargetAtAddress(address()); }
// Frame pointer for the frame that uses (calls) the IC. // Frame pointer for the frame that uses (calls) the IC.
Address fp_; Address fp_;
...@@ -391,7 +406,7 @@ class KeyedCallIC: public CallICBase { ...@@ -391,7 +406,7 @@ class KeyedCallIC: public CallICBase {
class LoadIC: public IC { class LoadIC: public IC {
public: public:
explicit LoadIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) { explicit LoadIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) {
ASSERT(target()->is_load_stub() || target()->is_keyed_load_stub()); ASSERT(IsLoadStub());
} }
// Code generator routines. // Code generator routines.
...@@ -468,9 +483,11 @@ class KeyedLoadIC: public LoadIC { ...@@ -468,9 +483,11 @@ class KeyedLoadIC: public LoadIC {
ASSERT(target()->is_keyed_load_stub()); ASSERT(target()->is_keyed_load_stub());
} }
MUST_USE_RESULT MaybeObject* LoadForceGeneric(Handle<Object> object,
Handle<Object> key);
MUST_USE_RESULT MaybeObject* Load(Handle<Object> object, MUST_USE_RESULT MaybeObject* Load(Handle<Object> object,
Handle<Object> key, Handle<Object> key);
ICMissMode force_generic);
// Code generator routines. // Code generator routines.
static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic); static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic);
...@@ -542,7 +559,7 @@ class StoreIC: public IC { ...@@ -542,7 +559,7 @@ class StoreIC: public IC {
StoreIC(FrameDepth depth, Isolate* isolate) StoreIC(FrameDepth depth, Isolate* isolate)
: IC(depth, isolate), : IC(depth, isolate),
strict_mode_(Code::GetStrictMode(target()->extra_ic_state())) { strict_mode_(Code::GetStrictMode(target()->extra_ic_state())) {
ASSERT(target()->is_store_stub() || target()->is_keyed_store_stub()); ASSERT(IsStoreStub());
} }
virtual StrictModeFlag strict_mode() const { return strict_mode_; } virtual StrictModeFlag strict_mode() const { return strict_mode_; }
...@@ -670,10 +687,12 @@ class KeyedStoreIC: public StoreIC { ...@@ -670,10 +687,12 @@ class KeyedStoreIC: public StoreIC {
ASSERT(target()->is_keyed_store_stub()); ASSERT(target()->is_keyed_store_stub());
} }
MUST_USE_RESULT MaybeObject* StoreForceGeneric(Handle<Object> object,
Handle<Object> name,
Handle<Object> value);
MUST_USE_RESULT MaybeObject* Store(Handle<Object> object, MUST_USE_RESULT MaybeObject* Store(Handle<Object> object,
Handle<Object> name, Handle<Object> name,
Handle<Object> value, Handle<Object> value);
ICMissMode force_generic);
// Code generators for stub routines. Only called once at startup. // Code generators for stub routines. Only called once at startup.
static void GenerateInitialize(MacroAssembler* masm) { static void GenerateInitialize(MacroAssembler* masm) {
...@@ -826,7 +845,7 @@ class CompareIC: public IC { ...@@ -826,7 +845,7 @@ class CompareIC: public IC {
: IC(EXTRA_CALL_FRAME, isolate), op_(op) { } : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
// Update the inline cache for the given operands. // Update the inline cache for the given operands.
void UpdateCaches(Handle<Object> x, Handle<Object> y); Code* UpdateCaches(Handle<Object> x, Handle<Object> y);
// Factory method for getting an uninitialized compare stub. // Factory method for getting an uninitialized compare stub.
...@@ -879,7 +898,7 @@ class ToBooleanIC: public IC { ...@@ -879,7 +898,7 @@ class ToBooleanIC: public IC {
public: public:
explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { } explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
MaybeObject* ToBoolean(Handle<Object> object, Code::ExtraICState state); MaybeObject* ToBoolean(Handle<Object> object);
}; };
......
...@@ -830,7 +830,7 @@ static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) { ...@@ -830,7 +830,7 @@ static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) {
// can't use either LoadIC or KeyedLoadIC constructors. // can't use either LoadIC or KeyedLoadIC constructors.
HandleScope scope(isolate); HandleScope scope(isolate);
IC ic(IC::NO_EXTRA_FRAME, isolate); IC ic(IC::NO_EXTRA_FRAME, isolate);
ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub()); ASSERT(ic.IsLoadStub());
if (!ic.SlowIsUndeclaredGlobal()) return isolate->heap()->undefined_value(); if (!ic.SlowIsUndeclaredGlobal()) return isolate->heap()->undefined_value();
// Throw a reference error. // Throw a reference error.
......
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