Commit 9be74766 authored by jkummerow's avatar jkummerow Committed by Commit bot

Reland^2 of [stubs] KeyedStoreGeneric: inline dictionary property stores

For dictionary-mode receivers, the KeyedStoreGeneric stub can store
properties directly in most cases. Doing so avoids the need to have
an entry in the stub cache for every map/property combination.

Original review: https://codereview.chromium.org/2504403005/

Review-Url: https://codereview.chromium.org/2528883003
Cr-Commit-Position: refs/heads/master@{#41272}
parent c4ccbaa3
...@@ -2566,10 +2566,9 @@ void Builtins::Generate_ArrayIteratorPrototypeNext( ...@@ -2566,10 +2566,9 @@ void Builtins::Generate_ArrayIteratorPrototypeNext(
Node* elements = Node* elements =
assembler.AllocateFixedArray(FAST_ELEMENTS, assembler.Int32Constant(2)); assembler.AllocateFixedArray(FAST_ELEMENTS, assembler.Int32Constant(2));
assembler.StoreFixedArrayElement(elements, assembler.Int32Constant(0), assembler.StoreFixedArrayElement(elements, 0, index, SKIP_WRITE_BARRIER);
index, SKIP_WRITE_BARRIER); assembler.StoreFixedArrayElement(elements, 1, var_value.value(),
assembler.StoreFixedArrayElement(elements, assembler.Int32Constant(1), SKIP_WRITE_BARRIER);
var_value.value(), SKIP_WRITE_BARRIER);
Node* entry = assembler.Allocate(JSArray::kSize); Node* entry = assembler.Allocate(JSArray::kSize);
Node* map = Node* map =
......
...@@ -293,8 +293,7 @@ compiler::Node* ConstructNewResultFromMatchInfo(Isolate* isolate, ...@@ -293,8 +293,7 @@ compiler::Node* ConstructNewResultFromMatchInfo(Isolate* isolate,
a->AllocateRegExpResult(context, num_results, start, string); a->AllocateRegExpResult(context, num_results, start, string);
Node* const result_elements = a->LoadElements(result); Node* const result_elements = a->LoadElements(result);
a->StoreFixedArrayElement(result_elements, a->IntPtrConstant(0), first, a->StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER);
SKIP_WRITE_BARRIER);
a->GotoIf(a->SmiEqual(num_results, a->SmiConstant(Smi::FromInt(1))), &out); a->GotoIf(a->SmiEqual(num_results, a->SmiConstant(Smi::FromInt(1))), &out);
...@@ -1846,7 +1845,7 @@ compiler::Node* ReplaceGlobalCallableFastPath( ...@@ -1846,7 +1845,7 @@ compiler::Node* ReplaceGlobalCallableFastPath(
Node* const replacement_str = a->ToString(context, replacement_obj); Node* const replacement_str = a->ToString(context, replacement_obj);
a->StoreFixedArrayElement(res_elems, index, replacement_str, a->StoreFixedArrayElement(res_elems, index, replacement_str,
UPDATE_WRITE_BARRIER, mode); UPDATE_WRITE_BARRIER, 0, mode);
a->Goto(&do_continue); a->Goto(&do_continue);
a->Bind(&do_continue); a->Bind(&do_continue);
......
This diff is collapsed.
...@@ -20,21 +20,24 @@ class StubCache; ...@@ -20,21 +20,24 @@ class StubCache;
enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol }; enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
#define HEAP_CONSTANT_LIST(V) \ #define HEAP_CONSTANT_LIST(V) \
V(BooleanMap, BooleanMap) \ V(AccessorInfoMap, AccessorInfoMap) \
V(CodeMap, CodeMap) \ V(BooleanMap, BooleanMap) \
V(empty_string, EmptyString) \ V(CodeMap, CodeMap) \
V(EmptyFixedArray, EmptyFixedArray) \ V(empty_string, EmptyString) \
V(FalseValue, False) \ V(EmptyFixedArray, EmptyFixedArray) \
V(FixedArrayMap, FixedArrayMap) \ V(FalseValue, False) \
V(FixedCOWArrayMap, FixedCOWArrayMap) \ V(FixedArrayMap, FixedArrayMap) \
V(FixedDoubleArrayMap, FixedDoubleArrayMap) \ V(FixedCOWArrayMap, FixedCOWArrayMap) \
V(HeapNumberMap, HeapNumberMap) \ V(FixedDoubleArrayMap, FixedDoubleArrayMap) \
V(MinusZeroValue, MinusZero) \ V(FunctionTemplateInfoMap, FunctionTemplateInfoMap) \
V(NanValue, Nan) \ V(HeapNumberMap, HeapNumberMap) \
V(NullValue, Null) \ V(MinusZeroValue, MinusZero) \
V(TheHoleValue, TheHole) \ V(NanValue, Nan) \
V(TrueValue, True) \ V(NullValue, Null) \
V(SymbolMap, SymbolMap) \
V(TheHoleValue, TheHole) \
V(TrueValue, True) \
V(UndefinedValue, Undefined) V(UndefinedValue, Undefined)
// Provides JavaScript-specific "macro-assembler" functionality on top of the // Provides JavaScript-specific "macro-assembler" functionality on top of the
...@@ -357,15 +360,15 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -357,15 +360,15 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Store an array element to a FixedArray. // Store an array element to a FixedArray.
compiler::Node* StoreFixedArrayElement( compiler::Node* StoreFixedArrayElement(
compiler::Node* object, int index, compiler::Node* value, compiler::Node* object, int index, compiler::Node* value,
WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) {
ParameterMode parameter_mode = INTEGER_PARAMETERS) { return StoreFixedArrayElement(object, IntPtrConstant(index), value,
return StoreFixedArrayElement(object, Int32Constant(index), value, barrier_mode, 0, INTPTR_PARAMETERS);
barrier_mode, parameter_mode);
} }
compiler::Node* StoreFixedArrayElement( compiler::Node* StoreFixedArrayElement(
compiler::Node* object, compiler::Node* index, compiler::Node* value, compiler::Node* object, compiler::Node* index, compiler::Node* value,
WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
int additional_offset = 0,
ParameterMode parameter_mode = INTEGER_PARAMETERS); ParameterMode parameter_mode = INTEGER_PARAMETERS);
compiler::Node* StoreFixedDoubleArrayElement( compiler::Node* StoreFixedDoubleArrayElement(
...@@ -762,16 +765,38 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -762,16 +765,38 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Calculate a valid size for the a hash table. // Calculate a valid size for the a hash table.
compiler::Node* HashTableComputeCapacity(compiler::Node* at_least_space_for); compiler::Node* HashTableComputeCapacity(compiler::Node* at_least_space_for);
template <class Dictionary>
compiler::Node* GetNumberOfElements(compiler::Node* dictionary);
template <class Dictionary>
void SetNumberOfElements(compiler::Node* dictionary,
compiler::Node* num_elements_smi);
template <class Dictionary>
compiler::Node* GetNumberOfDeletedElements(compiler::Node* dictionary);
template <class Dictionary>
compiler::Node* GetCapacity(compiler::Node* dictionary);
template <class Dictionary>
compiler::Node* GetNextEnumerationIndex(compiler::Node* dictionary);
template <class Dictionary>
void SetNextEnumerationIndex(compiler::Node* dictionary,
compiler::Node* next_enum_index_smi);
// Looks up an entry in a NameDictionaryBase successor. If the entry is found // Looks up an entry in a NameDictionaryBase successor. If the entry is found
// control goes to {if_found} and {var_name_index} contains an index of the // control goes to {if_found} and {var_name_index} contains an index of the
// key field of the entry found. If the key is not found control goes to // key field of the entry found. If the key is not found control goes to
// {if_not_found}. // {if_not_found}.
static const int kInlinedDictionaryProbes = 4; static const int kInlinedDictionaryProbes = 4;
enum LookupMode { kFindExisting, kFindInsertionIndex };
template <typename Dictionary> template <typename Dictionary>
void NameDictionaryLookup(compiler::Node* dictionary, void NameDictionaryLookup(compiler::Node* dictionary,
compiler::Node* unique_name, Label* if_found, compiler::Node* unique_name, Label* if_found,
Variable* var_name_index, Label* if_not_found, Variable* var_name_index, Label* if_not_found,
int inlined_probes = kInlinedDictionaryProbes); int inlined_probes = kInlinedDictionaryProbes,
LookupMode mode = kFindExisting);
compiler::Node* ComputeIntegerHash(compiler::Node* key, compiler::Node* seed); compiler::Node* ComputeIntegerHash(compiler::Node* key, compiler::Node* seed);
...@@ -780,6 +805,19 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -780,6 +805,19 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* intptr_index, Label* if_found, compiler::Node* intptr_index, Label* if_found,
Variable* var_entry, Label* if_not_found); Variable* var_entry, Label* if_not_found);
template <class Dictionary>
void FindInsertionEntry(compiler::Node* dictionary, compiler::Node* key,
Variable* var_key_index);
template <class Dictionary>
void InsertEntry(compiler::Node* dictionary, compiler::Node* key,
compiler::Node* value, compiler::Node* index,
compiler::Node* enum_index);
template <class Dictionary>
void Add(compiler::Node* dictionary, compiler::Node* key,
compiler::Node* value, Label* bailout);
// Tries to check if {object} has own {unique_name} property. // Tries to check if {object} has own {unique_name} property.
void TryHasOwnProperty(compiler::Node* object, compiler::Node* map, void TryHasOwnProperty(compiler::Node* object, compiler::Node* map,
compiler::Node* instance_type, compiler::Node* instance_type,
......
...@@ -2117,7 +2117,7 @@ void StoreScriptContextFieldStub::GenerateAssembly( ...@@ -2117,7 +2117,7 @@ void StoreScriptContextFieldStub::GenerateAssembly(
Node* script_context = assembler.LoadScriptContext(context, context_index()); Node* script_context = assembler.LoadScriptContext(context, context_index());
assembler.StoreFixedArrayElement( assembler.StoreFixedArrayElement(
script_context, assembler.IntPtrConstant(slot_index()), value, script_context, assembler.IntPtrConstant(slot_index()), value,
UPDATE_WRITE_BARRIER, CodeStubAssembler::INTPTR_PARAMETERS); UPDATE_WRITE_BARRIER, 0, CodeStubAssembler::INTPTR_PARAMETERS);
assembler.Return(value); assembler.Return(value);
} }
...@@ -2621,21 +2621,19 @@ compiler::Node* FastNewFunctionContextStub::Generate( ...@@ -2621,21 +2621,19 @@ compiler::Node* FastNewFunctionContextStub::Generate(
assembler->SmiFromWord32(length)); assembler->SmiFromWord32(length));
// Set up the fixed slots. // Set up the fixed slots.
assembler->StoreFixedArrayElement( assembler->StoreFixedArrayElement(function_context, Context::CLOSURE_INDEX,
function_context, assembler->Int32Constant(Context::CLOSURE_INDEX), function, SKIP_WRITE_BARRIER);
function, SKIP_WRITE_BARRIER); assembler->StoreFixedArrayElement(function_context, Context::PREVIOUS_INDEX,
assembler->StoreFixedArrayElement( context, SKIP_WRITE_BARRIER);
function_context, assembler->Int32Constant(Context::PREVIOUS_INDEX), assembler->StoreFixedArrayElement(function_context, Context::EXTENSION_INDEX,
context, SKIP_WRITE_BARRIER); assembler->TheHoleConstant(),
assembler->StoreFixedArrayElement( SKIP_WRITE_BARRIER);
function_context, assembler->Int32Constant(Context::EXTENSION_INDEX),
assembler->TheHoleConstant(), SKIP_WRITE_BARRIER);
// Copy the native context from the previous context. // Copy the native context from the previous context.
Node* native_context = assembler->LoadNativeContext(context); Node* native_context = assembler->LoadNativeContext(context);
assembler->StoreFixedArrayElement( assembler->StoreFixedArrayElement(function_context,
function_context, assembler->Int32Constant(Context::NATIVE_CONTEXT_INDEX), Context::NATIVE_CONTEXT_INDEX,
native_context, SKIP_WRITE_BARRIER); native_context, SKIP_WRITE_BARRIER);
// Initialize the rest of the slots to undefined. // Initialize the rest of the slots to undefined.
Node* undefined = assembler->UndefinedConstant(); Node* undefined = assembler->UndefinedConstant();
......
...@@ -1367,9 +1367,8 @@ void AccessorAssemblerImpl::KeyedLoadICGeneric(const LoadICParameters* p) { ...@@ -1367,9 +1367,8 @@ void AccessorAssemblerImpl::KeyedLoadICGeneric(const LoadICParameters* p) {
const int32_t kMaxLinear = 210; const int32_t kMaxLinear = 210;
Label stub_cache(this); Label stub_cache(this);
Node* bitfield3 = LoadMapBitField3(receiver_map); Node* bitfield3 = LoadMapBitField3(receiver_map);
Node* nof = Node* nof = DecodeWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3);
DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3); GotoIf(Uint32LessThan(Int32Constant(kMaxLinear), nof), &stub_cache);
GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), &stub_cache);
Node* descriptors = LoadMapDescriptors(receiver_map); Node* descriptors = LoadMapDescriptors(receiver_map);
Variable var_name_index(this, MachineType::PointerRepresentation()); Variable var_name_index(this, MachineType::PointerRepresentation());
Label if_descriptor_found(this); Label if_descriptor_found(this);
......
This diff is collapsed.
...@@ -3851,6 +3851,8 @@ class Dictionary: public HashTable<Derived, Shape, Key> { ...@@ -3851,6 +3851,8 @@ class Dictionary: public HashTable<Derived, Shape, Key> {
static const int kMaxNumberKeyIndex = DerivedHashTable::kPrefixStartIndex; static const int kMaxNumberKeyIndex = DerivedHashTable::kPrefixStartIndex;
static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1; static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
static const bool kIsEnumerable = Shape::kIsEnumerable;
protected: protected:
// Generic at put operation. // Generic at put operation.
MUST_USE_RESULT static Handle<Derived> AtPut( MUST_USE_RESULT static Handle<Derived> AtPut(
...@@ -9595,14 +9597,15 @@ class Symbol: public Name { ...@@ -9595,14 +9597,15 @@ class Symbol: public Name {
static const int kFlagsOffset = kNameOffset + kPointerSize; static const int kFlagsOffset = kNameOffset + kPointerSize;
static const int kSize = kFlagsOffset + kPointerSize; static const int kSize = kFlagsOffset + kPointerSize;
// Flags layout.
static const int kPrivateBit = 0;
static const int kWellKnownSymbolBit = 1;
typedef FixedBodyDescriptor<kNameOffset, kFlagsOffset, kSize> BodyDescriptor; typedef FixedBodyDescriptor<kNameOffset, kFlagsOffset, kSize> BodyDescriptor;
void SymbolShortPrint(std::ostream& os); void SymbolShortPrint(std::ostream& os);
private: private:
static const int kPrivateBit = 0;
static const int kWellKnownSymbolBit = 1;
const char* PrivateSymbolToName() const; const char* PrivateSymbolToName() const;
#if TRACE_MAPS #if TRACE_MAPS
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
function f(a, i, v) {
a[i] = v;
}
f("make it generic", 0, 0);
var a = new Array(3);
// Fast properties.
f(a, "length", 2);
assertEquals(2, a.length);
// Dictionary properties.
%OptimizeObjectForAddingMultipleProperties(a, 1);
f(a, "length", 1);
assertEquals(1, a.length);
...@@ -2,7 +2,30 @@ ...@@ -2,7 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax
class A {} class A {}
class B {} class B {}
Object.assign(B, A); Object.assign(B, A);
assertEquals("class B {}", B.toString()); assertEquals("class B {}", B.toString());
(function() {
function f(a, i, v) {
a[i] = v;
}
f("make it generic", 0, 0);
var o = {foo: "foo"};
%OptimizeObjectForAddingMultipleProperties(o, 10);
var s = %CreatePrivateSymbol("priv");
f(o, s, "private");
%ToFastProperties(o);
var desc = Object.getOwnPropertyDescriptor(o, s);
assertEquals("private", desc.value);
assertTrue(desc.writable);
assertFalse(desc.enumerable);
assertTrue(desc.configurable);
})();
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Test dictionary store ICs. // Test dictionary store ICs.
// Function that stores property 'x' on an object. // Function that stores property 'x' on an object.
...@@ -62,3 +64,27 @@ assertEquals(42, o.x); ...@@ -62,3 +64,27 @@ assertEquals(42, o.x);
delete o.x; delete o.x;
store(o); store(o);
assertEquals(42, o.x); assertEquals(42, o.x);
(function() {
var o = {};
for (var i = 0; i < 100; i++) {
var k = "key" + i;
o[k] = "foo";
delete o[k];
}
})();
(function() {
function f(a, i, v) {
a[i] = v;
}
f("make it generic", 0, 0);
var o = {};
for (var i = 0; i < 100; i++) {
var k = %InternalizeString("key" + i);
f(o, k, "foo");
delete o[k];
}
})();
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