Revision: 24500
Author: [email protected]
Date: Thu Oct 9 14:30:44 2014 UTC
Log: Add MEGAMORPHIC state support for KeyedStoreIC
[email protected]
Review URL: https://codereview.chromium.org/584043002
https://code.google.com/p/v8/source/detail?r=24500
Modified:
/branches/bleeding_edge/src/builtins.cc
/branches/bleeding_edge/src/builtins.h
/branches/bleeding_edge/src/ic/arm/ic-arm.cc
/branches/bleeding_edge/src/ic/arm64/ic-arm64.cc
/branches/bleeding_edge/src/ic/ia32/ic-ia32.cc
/branches/bleeding_edge/src/ic/ic.cc
/branches/bleeding_edge/src/ic/ic.h
/branches/bleeding_edge/src/ic/x64/ic-x64.cc
/branches/bleeding_edge/src/ic/x64/stub-cache-x64.cc
=======================================
--- /branches/bleeding_edge/src/builtins.cc Mon Sep 29 08:22:24 2014 UTC
+++ /branches/bleeding_edge/src/builtins.cc Thu Oct 9 14:30:44 2014 UTC
@@ -1312,15 +1312,25 @@
static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
}
+
+
+static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
+ KeyedStoreIC::GenerateGeneric(masm, SLOPPY, kMissOnMissingHandler);
+}
+
+
+static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm)
{
+ KeyedStoreIC::GenerateGeneric(masm, STRICT, kMissOnMissingHandler);
+}
static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
- KeyedStoreIC::GenerateGeneric(masm, SLOPPY);
+ KeyedStoreIC::GenerateGeneric(masm, SLOPPY,
kCallRuntimeOnMissingHandler);
}
static void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) {
- KeyedStoreIC::GenerateGeneric(masm, STRICT);
+ KeyedStoreIC::GenerateGeneric(masm, STRICT,
kCallRuntimeOnMissingHandler);
}
=======================================
--- /branches/bleeding_edge/src/builtins.h Mon Sep 22 13:23:27 2014 UTC
+++ /branches/bleeding_edge/src/builtins.h Thu Oct 9 14:30:44 2014 UTC
@@ -95,12 +95,15 @@
V(KeyedStoreIC_Initialize, KEYED_STORE_IC, UNINITIALIZED,
kNoExtraICState) \
V(KeyedStoreIC_PreMonomorphic, KEYED_STORE_IC,
PREMONOMORPHIC, \
kNoExtraICState) \
+ V(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, MEGAMORPHIC,
kNoExtraICState) \
V(KeyedStoreIC_Generic, KEYED_STORE_IC, GENERIC,
kNoExtraICState) \
\
V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC,
UNINITIALIZED, \
StoreIC::kStrictModeState) \
V(KeyedStoreIC_PreMonomorphic_Strict, KEYED_STORE_IC,
PREMONOMORPHIC, \
StoreIC::kStrictModeState) \
+ V(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC,
MEGAMORPHIC, \
+
StoreIC::kStrictModeState) \
V(KeyedStoreIC_Generic_Strict, KEYED_STORE_IC,
GENERIC, \
StoreIC::kStrictModeState) \
V(KeyedStoreIC_SloppyArguments, KEYED_STORE_IC,
MONOMORPHIC, \
=======================================
--- /branches/bleeding_edge/src/ic/arm/ic-arm.cc Mon Sep 22 13:23:27 2014
UTC
+++ /branches/bleeding_edge/src/ic/arm/ic-arm.cc Thu Oct 9 14:30:44 2014
UTC
@@ -765,8 +765,9 @@
}
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
- StrictMode strict_mode) {
+void KeyedStoreIC::GenerateGeneric(
+ MacroAssembler* masm, StrictMode strict_mode,
+ KeyedStoreStubCacheRequirement handler_requirement) {
// ---------- S t a t e --------------
// -- r0 : value
// -- r1 : key
@@ -775,7 +776,7 @@
// -----------------------------------
Label slow, fast_object, fast_object_grow;
Label fast_double, fast_double_grow;
- Label array, extra, check_if_double_array;
+ Label array, extra, check_if_double_array, maybe_name_key, miss;
// Register usage.
Register value = StoreDescriptor::ValueRegister();
@@ -790,7 +791,7 @@
// r4 and r5 are used as general scratch registers.
// Check that the key is a smi.
- __ JumpIfNotSmi(key, &slow);
+ __ JumpIfNotSmi(key, &maybe_name_key);
// Check that the object isn't a smi.
__ JumpIfSmi(receiver, &slow);
// Get the map of the object.
@@ -822,6 +823,23 @@
// r1: key.
// r2: receiver.
PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode);
+ // Never returns to here.
+
+ __ bind(&maybe_name_key);
+ __ ldr(r4, FieldMemOperand(key, HeapObject::kMapOffset));
+ __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
+ __ JumpIfNotUniqueNameInstanceType(r4, &slow);
+ Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
+ Code::ComputeHandlerFlags(Code::STORE_IC));
+ masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false,
receiver,
+ key, r3, r4, r5, r6);
+ // Cache miss.
+ if (handler_requirement == kCallRuntimeOnMissingHandler) {
+ __ b(&slow);
+ } else {
+ DCHECK(handler_requirement == kMissOnMissingHandler);
+ __ b(&miss);
+ }
// Extra capacity case: Check if there is extra capacity to
// perform the store and update the length. Used for adding one
@@ -863,6 +881,9 @@
&slow, kDontCheckMap, kIncrementLength,
value,
key, receiver, receiver_map,
elements_map,
elements);
+
+ __ bind(&miss);
+ GenerateMiss(masm);
}
=======================================
--- /branches/bleeding_edge/src/ic/arm64/ic-arm64.cc Mon Sep 22 13:23:27
2014 UTC
+++ /branches/bleeding_edge/src/ic/arm64/ic-arm64.cc Thu Oct 9 14:30:44
2014 UTC
@@ -798,8 +798,9 @@
}
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
- StrictMode strict_mode) {
+void KeyedStoreIC::GenerateGeneric(
+ MacroAssembler* masm, StrictMode strict_mode,
+ KeyedStoreStubCacheRequirement handler_requirement) {
ASM_LOCATION("KeyedStoreIC::GenerateGeneric");
Label slow;
Label array;
@@ -808,6 +809,8 @@
Label fast_object_grow;
Label fast_double_grow;
Label fast_double;
+ Label maybe_name_key;
+ Label miss;
Register value = StoreDescriptor::ValueRegister();
Register key = StoreDescriptor::NameRegister();
@@ -820,7 +823,7 @@
Register elements = x4;
Register elements_map = x5;
- __ JumpIfNotSmi(key, &slow);
+ __ JumpIfNotSmi(key, &maybe_name_key);
__ JumpIfSmi(receiver, &slow);
__ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
@@ -853,7 +856,23 @@
// x1: key
// x2: receiver
PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode);
+ // Never returns to here.
+ __ bind(&maybe_name_key);
+ __ Ldr(x10, FieldMemOperand(key, HeapObject::kMapOffset));
+ __ Ldrb(x10, FieldMemOperand(x10, Map::kInstanceTypeOffset));
+ __ JumpIfNotUniqueNameInstanceType(x10, &slow);
+ Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
+ Code::ComputeHandlerFlags(Code::STORE_IC));
+ masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false,
receiver,
+ key, x3, x4, x5, x6);
+ // Cache miss.
+ if (handler_requirement == kCallRuntimeOnMissingHandler) {
+ __ B(&slow);
+ } else {
+ DCHECK(handler_requirement == kMissOnMissingHandler);
+ __ B(&miss);
+ }
__ Bind(&extra);
// Extra capacity case: Check if there is extra capacity to
@@ -895,6 +914,11 @@
&slow, kDontCheckMap, kIncrementLength,
value,
key, receiver, receiver_map,
elements_map,
elements);
+
+ if (handler_requirement == kMissOnMissingHandler) {
+ __ bind(&miss);
+ GenerateMiss(masm);
+ }
}
=======================================
--- /branches/bleeding_edge/src/ic/ia32/ic-ia32.cc Mon Sep 22 13:23:27 2014
UTC
+++ /branches/bleeding_edge/src/ic/ia32/ic-ia32.cc Thu Oct 9 14:30:44 2014
UTC
@@ -672,12 +672,13 @@
}
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
- StrictMode strict_mode) {
+void KeyedStoreIC::GenerateGeneric(
+ MacroAssembler* masm, StrictMode strict_mode,
+ KeyedStoreStubCacheRequirement handler_requirement) {
// Return address is on the stack.
Label slow, fast_object, fast_object_grow;
Label fast_double, fast_double_grow;
- Label array, extra, check_if_double_array;
+ Label array, extra, check_if_double_array, maybe_name_key, miss;
Register receiver = StoreDescriptor::ReceiverRegister();
Register key = StoreDescriptor::NameRegister();
DCHECK(receiver.is(edx));
@@ -693,7 +694,7 @@
1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved);
__ j(not_zero, &slow);
// Check that the key is a smi.
- __ JumpIfNotSmi(key, &slow);
+ __ JumpIfNotSmi(key, &maybe_name_key);
__ CmpInstanceType(edi, JS_ARRAY_TYPE);
__ j(equal, &array);
// Check that the object is some kind of JSObject.
@@ -711,6 +712,23 @@
// Slow case: call runtime.
__ bind(&slow);
PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode);
+ // Never returns to here.
+
+ __ bind(&maybe_name_key);
+ __ mov(ebx, FieldOperand(key, HeapObject::kMapOffset));
+ __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
+ __ JumpIfNotUniqueNameInstanceType(ebx, &slow);
+ Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
+ Code::ComputeHandlerFlags(Code::STORE_IC));
+ masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false,
receiver,
+ key, ebx, no_reg);
+ // Cache miss.
+ if (handler_requirement == kCallRuntimeOnMissingHandler) {
+ __ jmp(&slow);
+ } else {
+ DCHECK(handler_requirement == kMissOnMissingHandler);
+ __ jmp(&miss);
+ }
// Extra capacity case: Check if there is extra capacity to
// perform the store and update the length. Used for adding one
@@ -753,6 +771,11 @@
kCheckMap, kDontIncrementLength);
KeyedStoreGenerateGenericHelper(masm, &fast_object_grow,
&fast_double_grow,
&slow, kDontCheckMap, kIncrementLength);
+
+ if (handler_requirement == kMissOnMissingHandler) {
+ __ bind(&miss);
+ GenerateMiss(masm);
+ }
}
=======================================
--- /branches/bleeding_edge/src/ic/ic.cc Wed Oct 8 09:15:09 2014 UTC
+++ /branches/bleeding_edge/src/ic/ic.cc Thu Oct 9 14:30:44 2014 UTC
@@ -801,18 +801,26 @@
case POLYMORPHIC:
if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) {
if (UpdatePolymorphicIC(name, code)) break;
+ // For keyed stubs, we can't know whether old handlers were for the
+ // same key.
CopyICToMegamorphicCache(name);
}
set_target(*megamorphic_stub());
// Fall through.
case MEGAMORPHIC:
UpdateMegamorphicCache(*receiver_type(), *name, *code);
+ // Indicate that we've handled this case.
+ target_set_ = true;
break;
case DEBUG_STUB:
break;
case DEFAULT:
+ UNREACHABLE();
+ break;
case GENERIC:
- UNREACHABLE();
+ // The generic keyed store stub re-uses store handlers, which can
miss.
+ // That's ok, no reason to do anything.
+ DCHECK(target()->kind() == Code::KEYED_STORE_IC);
break;
}
}
@@ -894,7 +902,8 @@
void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) {
- if (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)
return;
+ // Megamorphic state isn't implemented for keyed loads currently.
+ if (kind() == Code::KEYED_LOAD_IC) return;
Map* map = *TypeToMap(type, isolate());
isolate()->stub_cache()->Set(name, map, code);
}
@@ -1365,9 +1374,9 @@
} else {
DCHECK(kind() == Code::KEYED_STORE_IC);
if (strict_mode() == STRICT) {
- return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
+ return isolate()->builtins()->KeyedStoreIC_Megamorphic_Strict();
} else {
- return isolate()->builtins()->KeyedStoreIC_Generic();
+ return isolate()->builtins()->KeyedStoreIC_Megamorphic();
}
}
}
@@ -1813,12 +1822,12 @@
StoreIC::Store(object, Handle<String>::cast(key), value,
JSReceiver::MAY_BE_STORE_FROM_KEYED),
Object);
- // TODO(jkummerow): Ideally we'd wrap this in "if (!is_target_set())",
- // but doing so causes Hydrogen crashes. Needs investigation.
- TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
- "unhandled internalized string key");
- TRACE_IC("StoreIC", key);
- set_target(*stub);
+ if (!is_target_set()) {
+ TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
+ "unhandled internalized string key");
+ TRACE_IC("StoreIC", key);
+ set_target(*stub);
+ }
return store_handle;
}
@@ -2088,7 +2097,7 @@
DCHECK(args.length() == 3);
StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
Handle<Object> receiver = args.at<Object>(0);
- Handle<String> key = args.at<String>(1);
+ Handle<Name> key = args.at<Name>(1);
ic.UpdateState(receiver, key);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
@@ -2103,7 +2112,7 @@
DCHECK(args.length() == 3 || args.length() == 4);
StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
Handle<Object> receiver = args.at<Object>(0);
- Handle<String> key = args.at<String>(1);
+ Handle<Name> key = args.at<Name>(1);
ic.UpdateState(receiver, key);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
=======================================
--- /branches/bleeding_edge/src/ic/ic.h Wed Oct 8 09:15:09 2014 UTC
+++ /branches/bleeding_edge/src/ic/ic.h Thu Oct 9 14:30:44 2014 UTC
@@ -223,7 +223,6 @@
return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
}
- protected:
inline void UpdateTarget();
private:
@@ -526,6 +525,12 @@
enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength };
+enum KeyedStoreStubCacheRequirement {
+ kCallRuntimeOnMissingHandler,
+ kMissOnMissingHandler
+};
+
+
class KeyedStoreIC : public StoreIC {
public:
// ExtraICState bits (building on IC)
@@ -559,7 +564,9 @@
}
static void GenerateMiss(MacroAssembler* masm);
static void GenerateSlow(MacroAssembler* masm);
- static void GenerateGeneric(MacroAssembler* masm, StrictMode
strict_mode);
+ static void GenerateGeneric(
+ MacroAssembler* masm, StrictMode strict_mode,
+ KeyedStoreStubCacheRequirement handler_requirement);
static void GenerateSloppyArguments(MacroAssembler* masm);
protected:
=======================================
--- /branches/bleeding_edge/src/ic/x64/ic-x64.cc Mon Sep 22 13:23:27 2014
UTC
+++ /branches/bleeding_edge/src/ic/x64/ic-x64.cc Thu Oct 9 14:30:44 2014
UTC
@@ -566,12 +566,13 @@
}
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
- StrictMode strict_mode) {
+void KeyedStoreIC::GenerateGeneric(
+ MacroAssembler* masm, StrictMode strict_mode,
+ KeyedStoreStubCacheRequirement handler_requirement) {
// Return address is on the stack.
Label slow, slow_with_tagged_index, fast_object, fast_object_grow;
Label fast_double, fast_double_grow;
- Label array, extra, check_if_double_array;
+ Label array, extra, check_if_double_array, maybe_name_key, miss;
Register receiver = StoreDescriptor::ReceiverRegister();
Register key = StoreDescriptor::NameRegister();
DCHECK(receiver.is(rdx));
@@ -587,7 +588,7 @@
Immediate(1 << Map::kIsAccessCheckNeeded | 1 <<
Map::kIsObserved));
__ j(not_zero, &slow_with_tagged_index);
// Check that the key is a smi.
- __ JumpIfNotSmi(key, &slow_with_tagged_index);
+ __ JumpIfNotSmi(key, &maybe_name_key);
__ SmiToInteger32(key, key);
__ CmpInstanceType(r9, JS_ARRAY_TYPE);
@@ -609,6 +610,22 @@
__ bind(&slow_with_tagged_index);
PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode);
// Never returns to here.
+
+ __ bind(&maybe_name_key);
+ __ movp(r9, FieldOperand(key, HeapObject::kMapOffset));
+ __ movzxbp(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
+ __ JumpIfNotUniqueNameInstanceType(r9, &slow_with_tagged_index);
+ Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
+ Code::ComputeHandlerFlags(Code::STORE_IC));
+ masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false,
receiver,
+ key, rbx, no_reg);
+ // Cache miss.
+ if (handler_requirement == kCallRuntimeOnMissingHandler) {
+ __ jmp(&slow_with_tagged_index);
+ } else {
+ DCHECK(handler_requirement == kMissOnMissingHandler);
+ __ jmp(&miss);
+ }
// Extra capacity case: Check if there is extra capacity to
// perform the store and update the length. Used for adding one
@@ -648,6 +665,11 @@
kCheckMap, kDontIncrementLength);
KeyedStoreGenerateGenericHelper(masm, &fast_object_grow,
&fast_double_grow,
&slow, kDontCheckMap, kIncrementLength);
+
+ if (handler_requirement == kMissOnMissingHandler) {
+ __ bind(&miss);
+ GenerateMiss(masm);
+ }
}
=======================================
--- /branches/bleeding_edge/src/ic/x64/stub-cache-x64.cc Mon Sep 8
12:51:29 2014 UTC
+++ /branches/bleeding_edge/src/ic/x64/stub-cache-x64.cc Thu Oct 9
14:30:44 2014 UTC
@@ -41,14 +41,14 @@
__ LoadAddress(kScratchRegister, key_offset);
// Check that the key in the entry matches the name.
- // Multiply entry offset by 16 to get the entry address. Since the
- // offset register already holds the entry offset times four, multiply
- // by a further four.
- __ cmpl(name, Operand(kScratchRegister, offset, scale_factor, 0));
+ __ cmpp(name, Operand(kScratchRegister, offset, scale_factor, 0));
__ j(not_equal, &miss);
// Get the map entry from the cache.
// Use key_offset + kPointerSize * 2, rather than loading map_offset.
+ DCHECK(isolate->stub_cache()->map_reference(table).address() -
+ isolate->stub_cache()->key_reference(table).address() ==
+ kPointerSize * 2);
__ movp(kScratchRegister,
Operand(kScratchRegister, offset, scale_factor, kPointerSize *
2));
__ cmpp(kScratchRegister, FieldOperand(receiver,
HeapObject::kMapOffset));
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.