Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(732)

Unified Diff: src/ic.cc

Issue 9310117: Implement KeyedStoreICs to grow arrays on out-of-bound stores. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add missing WB stub Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ic.cc
diff --git a/src/ic.cc b/src/ic.cc
index 9846984dd383c4488e3bb20e0db4685751926e4f..248f4fc891d16430d602c613c81deb21badbaf86 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -81,9 +81,13 @@ void IC::TraceIC(const char* type,
}
}
JavaScriptFrame::PrintTop(stdout, false, true);
- PrintF(" (%c->%c)",
+ bool new_can_grow =
+ Code::GetKeyedAccessGrowMode(new_target->extra_ic_state()) ==
+ ALLOW_JSARRAY_GROWTH;
+ PrintF(" (%c->%c%s)",
TransitionMarkFromState(old_state),
- TransitionMarkFromState(new_state));
+ TransitionMarkFromState(new_state),
+ new_can_grow ? ".GROW" : "");
name->Print();
PrintF("]\n");
}
@@ -375,7 +379,7 @@ void LoadIC::Clear(Address address, Code* target) {
void StoreIC::Clear(Address address, Code* target) {
if (target->ic_state() == UNINITIALIZED) return;
SetTargetAtAddress(address,
- (target->extra_ic_state() == kStrictMode)
+ (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
? initialize_stub_strict()
: initialize_stub());
}
@@ -384,7 +388,7 @@ void StoreIC::Clear(Address address, Code* target) {
void KeyedStoreIC::Clear(Address address, Code* target) {
if (target->ic_state() == UNINITIALIZED) return;
SetTargetAtAddress(address,
- (target->extra_ic_state() == kStrictMode)
+ (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
? initialize_stub_strict()
: initialize_stub());
}
@@ -996,19 +1000,22 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
Handle<Code> KeyedLoadIC::GetElementStubWithoutMapCheck(
bool is_js_array,
- ElementsKind elements_kind) {
+ ElementsKind elements_kind,
+ KeyedAccessGrowMode grow_mode) {
+ ASSERT(grow_mode == DO_NOT_ALLOW_JSARRAY_GROWTH);
return KeyedLoadElementStub(elements_kind).GetCode();
}
Handle<Code> KeyedLoadIC::ComputePolymorphicStub(
MapHandleList* receiver_maps,
- StrictModeFlag strict_mode) {
+ StrictModeFlag strict_mode,
+ KeyedAccessGrowMode growth_mode) {
CodeHandleList handler_ics(receiver_maps->length());
for (int i = 0; i < receiver_maps->length(); ++i) {
Handle<Map> receiver_map = receiver_maps->at(i);
Handle<Code> cached_stub = ComputeMonomorphicStubWithoutMapCheck(
- receiver_map, strict_mode);
+ receiver_map, strict_mode, growth_mode);
handler_ics.Add(cached_stub);
}
KeyedLoadStubCompiler compiler(isolate());
@@ -1493,6 +1500,9 @@ Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
StrictModeFlag strict_mode,
Handle<Code> generic_stub) {
State ic_state = target()->ic_state();
+ KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind)
+ ? ALLOW_JSARRAY_GROWTH
+ : DO_NOT_ALLOW_JSARRAY_GROWTH;
if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) &&
!IsTransitionStubKind(stub_kind)) {
return ComputeMonomorphicStub(
@@ -1537,14 +1547,21 @@ Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
return generic_stub;
}
+ if ((Code::GetKeyedAccessGrowMode(target()->extra_ic_state()) ==
+ ALLOW_JSARRAY_GROWTH)) {
+ grow_mode = ALLOW_JSARRAY_GROWTH;
+ }
+
Handle<PolymorphicCodeCache> cache =
isolate()->factory()->polymorphic_code_cache();
- Code::Flags flags = Code::ComputeFlags(kind(), MEGAMORPHIC, strict_mode);
+ Code::ExtraICState extra_state = Code::ComputeExtraICState(grow_mode,
+ strict_mode);
+ Code::Flags flags = Code::ComputeFlags(kind(), MEGAMORPHIC, extra_state);
Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags);
if (probe->IsCode()) return Handle<Code>::cast(probe);
Handle<Code> stub =
- ComputePolymorphicStub(&target_receiver_maps, strict_mode);
+ ComputePolymorphicStub(&target_receiver_maps, strict_mode, grow_mode);
PolymorphicCodeCache::Update(cache, &target_receiver_maps, flags, stub);
return stub;
}
@@ -1552,7 +1569,8 @@ Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
Handle<Code> KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
Handle<Map> receiver_map,
- StrictModeFlag strict_mode) {
+ StrictModeFlag strict_mode,
+ KeyedAccessGrowMode grow_mode) {
if ((receiver_map->instance_type() & kNotStringTag) == 0) {
ASSERT(!string_stub().is_null());
return string_stub();
@@ -1564,7 +1582,8 @@ Handle<Code> KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
receiver_map->has_external_array_elements());
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
return GetElementStubWithoutMapCheck(is_js_array,
- receiver_map->elements_kind());
+ receiver_map->elements_kind(),
+ grow_mode);
}
}
@@ -1591,9 +1610,12 @@ Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver,
switch (stub_kind) {
case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT:
case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT:
+ case KeyedIC::STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT:
+ case KeyedIC::STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT:
return JSObject::GetElementsTransitionMap(receiver, FAST_ELEMENTS);
break;
case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE:
+ case KeyedIC::STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE:
return JSObject::GetElementsTransitionMap(receiver, FAST_DOUBLE_ELEMENTS);
break;
default:
@@ -1605,13 +1627,16 @@ Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver,
Handle<Code> KeyedStoreIC::GetElementStubWithoutMapCheck(
bool is_js_array,
- ElementsKind elements_kind) {
- return KeyedStoreElementStub(is_js_array, elements_kind).GetCode();
+ ElementsKind elements_kind,
+ KeyedAccessGrowMode grow_mode) {
+ return KeyedStoreElementStub(is_js_array, elements_kind, grow_mode).GetCode();
}
-Handle<Code> KeyedStoreIC::ComputePolymorphicStub(MapHandleList* receiver_maps,
- StrictModeFlag strict_mode) {
+Handle<Code> KeyedStoreIC::ComputePolymorphicStub(
+ MapHandleList* receiver_maps,
+ StrictModeFlag strict_mode,
+ KeyedAccessGrowMode grow_mode) {
// Collect MONOMORPHIC stubs for all target_receiver_maps.
CodeHandleList handler_ics(receiver_maps->length());
MapHandleList transitioned_maps(receiver_maps->length());
@@ -1625,16 +1650,17 @@ Handle<Code> KeyedStoreIC::ComputePolymorphicStub(MapHandleList* receiver_maps,
receiver_map->elements_kind(), // original elements_kind
transitioned_map->elements_kind(),
receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array
- strict_mode).GetCode();
+ strict_mode, grow_mode).GetCode();
} else {
cached_stub = ComputeMonomorphicStubWithoutMapCheck(receiver_map,
- strict_mode);
+ strict_mode,
+ grow_mode);
}
ASSERT(!cached_stub.is_null());
handler_ics.Add(cached_stub);
transitioned_maps.Add(transitioned_map);
}
- KeyedStoreStubCompiler compiler(isolate(), strict_mode);
+ KeyedStoreStubCompiler compiler(isolate(), strict_mode, grow_mode);
Handle<Code> code = compiler.CompileStorePolymorphic(
receiver_maps, &handler_ics, &transitioned_maps);
isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
@@ -1644,6 +1670,48 @@ Handle<Code> KeyedStoreIC::ComputePolymorphicStub(MapHandleList* receiver_maps,
}
+KeyedIC::StubKind KeyedStoreIC::GetStubKind(Handle<JSObject> receiver,
+ Handle<Object> key,
+ Handle<Object> value) {
+ ASSERT(key->IsSmi());
+ int index = Smi::cast(*key)->value();
+ bool allow_growth = receiver->IsJSArray() &&
+ JSArray::cast(*receiver)->length()->IsSmi() &&
+ index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
+
+ if (allow_growth) {
+ // Handle growing array in stub if necessary.
+ if (receiver->HasFastSmiOnlyElements()) {
+ if (value->IsHeapNumber()) {
+ return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE;
+ }
+ if (value->IsHeapObject()) {
+ return STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT;
+ }
+ } else if (receiver->HasFastDoubleElements()) {
+ if (!value->IsSmi() && !value->IsHeapNumber()) {
+ return STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT;
+ }
+ }
+ return STORE_AND_GROW_NO_TRANSITION;
+ } else {
+ // Handle only in-bounds elements accesses.
+ if (receiver->HasFastSmiOnlyElements()) {
+ if (value->IsHeapNumber()) {
+ return STORE_TRANSITION_SMI_TO_DOUBLE;
+ } else if (value->IsHeapObject()) {
+ return STORE_TRANSITION_SMI_TO_OBJECT;
+ }
+ } else if (receiver->HasFastDoubleElements()) {
+ if (!value->IsSmi() && !value->IsHeapNumber()) {
+ return STORE_TRANSITION_DOUBLE_TO_OBJECT;
+ }
+ }
+ return STORE_NO_TRANSITION;
+ }
+}
+
+
MaybeObject* KeyedStoreIC::Store(State state,
StrictModeFlag strict_mode,
Handle<Object> object,
@@ -1706,18 +1774,7 @@ MaybeObject* KeyedStoreIC::Store(State state,
stub = non_strict_arguments_stub();
} else if (!force_generic) {
if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
- StubKind stub_kind = STORE_NO_TRANSITION;
- if (receiver->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) {
- if (value->IsHeapNumber()) {
- stub_kind = STORE_TRANSITION_SMI_TO_DOUBLE;
- } else if (value->IsHeapObject()) {
- stub_kind = STORE_TRANSITION_SMI_TO_OBJECT;
- }
- } else if (receiver->GetElementsKind() == FAST_DOUBLE_ELEMENTS) {
- if (!value->IsSmi() && !value->IsHeapNumber()) {
- stub_kind = STORE_TRANSITION_DOUBLE_TO_OBJECT;
- }
- }
+ StubKind stub_kind = GetStubKind(receiver, key, value);
stub = ComputeStub(receiver, stub_kind, strict_mode, stub);
}
} else {
@@ -1900,7 +1957,7 @@ RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
return ic.Store(state,
- static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
+ Code::GetStrictMode(extra_ic_state),
args.at<Object>(0),
args.at<String>(1),
args.at<Object>(2));
@@ -1976,7 +2033,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
return ic.Store(state,
- static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
+ Code::GetStrictMode(extra_ic_state),
args.at<Object>(0),
args.at<Object>(1),
args.at<Object>(2),
@@ -1992,8 +2049,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
Handle<Object> object = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1);
Handle<Object> value = args.at<Object>(2);
- StrictModeFlag strict_mode =
- static_cast<StrictModeFlag>(extra_ic_state & kStrictMode);
+ StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state);
return Runtime::SetObjectProperty(isolate,
object,
key,
@@ -2010,7 +2066,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
return ic.Store(state,
- static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
+ Code::GetStrictMode(extra_ic_state),
args.at<Object>(0),
args.at<Object>(1),
args.at<Object>(2),
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698